배경

MySQL은 전체 텍스트(Full-Text index) 인덱싱 및 검색을 지원합니다.

기존의 로직에서는 Like 연산자를 이용하였고 단일 테스트에서 처참한 결과를 보여주었습니다.

데이터베이스는 조건문으로 검색할 대, 테이블 전체를 full scan으로 탐색한다. 이러한 탐색방식은 1000만건 이상의 상품을 조회하는 우리 프로젝트에서는 시간적으로 비효율적인 방식이라는 것을 알 수 있습니다.

인덱스는 Balance tree(B-Tree) 알고리즘을 따른다. O(n)의 시간복잡도가 걸리는 방식을 O(logn)시간으로 탐색을 마칠 수 있다. 데이터가 증가할 수록, 즉 대용량의 데이터를 다루는 우리의 프로젝트의 경우 두 개의 차이는 확연히 드러나게 됩니다.

상품 테이블의 경우 UPDATE, INSERT, DELETE 의 쿼리 보다 상대적으로 SELECT 의 쿼리가 사용되었고 Table 의 Index 색인 정보를 갱신하는 추가적인 비용이 발생하지 않기에 카테고리별 상품을 불러오는 로직에 인덱스를 적용하기로 하였습니다.

상품의 카테고리별 카디날리티는 높은 편은 아니며 읽어야 할 레코드의 건수가 전체 테이블 레코드의 20프로를 넘기는 경우가 거의 없기에, 또한 Repository 에서 Where 절을 사용하기에 인덱스를 사용하여 효과를 기대하였습니다.

index 를 적용하기에 앞서 Like 문으로 코드 작성하였다.

Service Logic
List<ProductResponseDto> productResponseDtoList
 = productRepository.findAllByTitleContains(query).stream().map(ProductResponseDto::new).toList();
====
Repository Logic
@Query("select p from Product p where p.title like %:query%")*List*<Product> findAllByTitleContains(@Param("query") String query);

적용

Product Entity → Table Index 적용

Untitled

category1 Column index 적용 완료

Untitled