인프런 커뮤니티 질문&답변

오지윤님의 프로필 이미지

작성한 질문수

실전! Django 활용

상품 주문(Order)

product의 name 필드로 상품 검색시 생성한 gin index사용 여부

해결된 질문

24.07.27 19:19 작성

·

107

·

수정됨

0

안녕하세요 강사님!

상품검색 - 한글 full-text search 구현 부분 듣다가 궁금한 점이 생겨 질문 남깁니다.

product_list_handler에서 query가 있을 때, products를 필터하는 orm에서 100개로 갯수를 제한하는데요.

강의에서처럼 explain으로 쿼리 실행계획을 볼 때, 데이터가 얼마 없을때는 full scan을 하고, 많으면 모델에서 생성한 'product_name_gin_index'를 통해 scan을 하더라구요.

언제부터 인덱스에서 스캔하나 궁금해서 limit를 늘려가면서 확인했는데, 제 로컬에서는 limit가 12,800개가 넘어갈 때 인덱스를 사용하더라구요. 이렇게 되면 100개로 제한해서 쿼리하면 어차피 인덱스를 사용하지 않을것 같은데 맞나요?

맞다면 결과적으로 product_name_gin_index 인덱스를 사용하지 않는데, 이 인덱스를 생성한게 의미가 있을까요?? 응답할 때 페이지네이션을 필요하니까 한번에 10,000개 이상 보낼 일은 없을 것 같은데 인덱스를 생성한 장점이 있는지 궁금합니다!

def product_list_handler(
    request: HttpRequest, category_id: int | None = None, query: str | None = None
):
    """
    쿼리 파라미터인 category_id, query에 따라 상품 목록 조회 API
    """
    if query:
        products = Product.objects.filter(
            name__contains=query, status=ProductStatus.ACTIVE
        )[:100]

    ... (생략)
    pass

답변 1

0

신동현님의 프로필 이미지
신동현
지식공유자

2024. 07. 27. 19:34

안녕하세요! 말씀 주신 테스트 상황이 데이터를 충분히 많이 생성한 상태에서 limit을 100개로 쿼리한 경우에 풀 스캔을 사용하였다는 말일까요?

 

데이터가 적은 경우에는 몇 개를 쿼리하든 풀 스캔을 사용할 확률이 높습니다. (정확한 임계치는 데이터베이스 엔진에서 결정하기 때문에 상황에 따라 달라집니다.)

 

데이터가 충분히 많은 경우에는 반대로 index를 활용할 확률이 높아집니다. 실제로 제가 실습에서 보여드린 예제에서도 실습 쿼리 문에 limit을 지정하진 않았지만 IDE에 의해서 자동으로 limit이 500으로 고정되어 있습니다! 

예외적으로 데이터가 충분히 많더라도 전체를 전부 스캔하려고 하면 풀 스캔이 사용될 수도 있습니다.

오지윤님의 프로필 이미지
오지윤
질문자

2024. 07. 27. 19:48

네 맞습니다! 아 캡쳐한 사진을 첨부해서 다시 여쭤볼게요.

강의에서처럼 10만개를 생성한 후 '멋있는'이 들어있는 상품을 쿼리할 때 실행계획을 캡쳐했는데요.

  1. limit이 없는 경우 인덱스 사용

    인덱스에서스캔.png

  2. limit 100인 경우 인덱스 사용하지 않음

    limit_100.png

    이런 상황에서 상품검색 API에서 아래처럼 쿼리하면 인덱스를 사용하지 않는것 같아서 인덱스 생성한게 의미가 있을까요??

     products = Product.objects.filter(
                name__contains=query, status=ProductStatus.ACTIVE
            )[:100]
신동현님의 프로필 이미지
신동현
지식공유자

2024. 07. 27. 20:03

혹시 limit 500으로 하면 어떻게 출력되나요?

오지윤님의 프로필 이미지
오지윤
질문자

2024. 07. 27. 20:26

같았어요! 그래서 어느 순간에 인덱스를 사용하나 궁금해서 숫자를 계속 늘려봤을 때, 제 로컬에서는 limit 12800일 때 사용하더라구요!
1. limit 500

limit_500.png

  1. limit 12800

limit_12800.png

신동현님의 프로필 이미지
신동현
지식공유자

2024. 07. 27. 20:43

네, 사실 10만개도 큰 데이터 셋은 아니라서 경우에 따라 풀 스캔이 사용되는 것 같네요. 말씀 주신 것처럼 평소 사용하는 쿼리를 통해 실행계획을 분석해서 index 생성이 불필요하다면 굳이 index를 생성하지 않아도 됩니다!

제 로컬 환경에서는 레코드를 200만개 정도 생성하고 limit 100으로 실행해보니 index를 사용하네요.

오지윤님의 프로필 이미지
오지윤
질문자

2024. 07. 27. 21:04

아하 데이터셋에 따라 달라지는군요.. 저도 데이터 늘려가면서 한번 테스트 해보겠습니다. 덕분에 궁금한 부분이 풀렸습니다. 남은 강의도 잘 듣겠습니다!! tmi로 어제 redis와 sql 강의도 구매해두었습니다 ㅎㅎ 빠르게 답변해주셔서 감사드립니다~~!!!!👍🏻