전체 텍스트 검색

FTS 및 N1QL: 다중 배열을 쿼리하는 연산자 성능의 MongoDB 향상

소개

Couchbase 전체 텍스트 검색(FTS)은 여러 배열을 색인하고 배열에 여러 필터 술어를 사용하여 쿼리를 실행하는 데 매우 적합합니다. 이 글에서는 여러 배열을 쿼리해야 하는 예제 사용 사례를 살펴보면서 배열 인덱싱에 GSI(글로벌 보조 인덱스)보다 FTS를 사용할 때의 이점을 보여드리겠습니다. FTS 다중 배열 인덱스를 생성하고 Couchbase Server 6.5에 도입된 새로운 SEARCH() 함수를 사용하여 N1QL로 인덱스를 쿼리할 것입니다.  

여행 샘플 버킷

이 문서에서는 다음과 같이 참조할 것입니다. 설치 가능한 여행 샘플 데이터 세트 를 추가할 수 있습니다. 여행 샘플 버킷에는 항공사, 노선, 공항, 랜드마크, 호텔 등 여러 가지 문서 유형이 있습니다. 각 문서 유형에 대한 문서 모델에는 다음이 포함됩니다:

  • 기본 키 역할을 하는 키
  • 문서를 식별하는 ID 필드
  • 문서의 종류를 식별하는 유형 필드입니다.

 

이 글의 예제에서는 호텔 문서를 사용합니다. 아래 샘플 문서를 통해 호텔 문서의 구조에 대한 아이디어를 얻을 수 있습니다: 

그림 1 - 호텔 문서 샘플

문제

이 예는 사용자가 특정 이름을 가진 사람이 리뷰를 남기거나 좋아요를 누른 호텔을 검색하는 사용 사례입니다. 이를 위해서는 호텔 문서 모델 내의 배열인 공개 좋아요와 리뷰 모두에 대해 호텔 문서를 쿼리해야 합니다: 

그림 2 - 샘플 호텔 문서의 "public_likes" 및 "reviews" 배열

 

먼저 이 사용 사례를 N1QL과 GSI(글로벌 보조 인덱스)로 구현하는 방법을 살펴봅시다. Ozella라는 이름의 사용자가 좋아요를 누르거나 리뷰를 남긴 호텔을 찾으려면 쿼리는 다음과 같이 작성할 수 있습니다: 

 

이 쿼리에 적합한 인덱스를 만들어야 합니다. 호텔 문서에 대한 관심 배열을 모두 색인하는 이와 같은 색인을 만들 수 있습니다: 

 

이 방법은 작동하지 않으며 그림 3에 표시된 오류가 발생합니다:

그림 3 - 다중 배열을 사용한 인덱스 생성 오류

 

케샤브 머시는 블로그 게시물에서 다음과 같이 썼습니다. 검색 및 구조 N1QL(SQL) 개발자가 Search를 사용해야 하는 7가지 이유 (문제 #6), 카우치베이스에서 N1QL 사용, "배열 내부를 검색하는 동안 최상의 성능을 얻으려면 다음을 수행해야 합니다. 배열 키로 인덱스 생성. 배열 인덱스에는 각 배열 인덱스당 하나의 배열 키만 가질 수 있다는 제한이 있습니다. 따라서 여러 배열 필드가 있는 고객 개체가 있는 경우 단일 인덱스를 사용하여 모든 필드를 검색할 수 없으므로 쿼리 비용이 많이 듭니다." Keshav가 이 글에서 언급했듯이, 이는 일반적으로 데이터베이스의 b-tree 인덱스가 갖는 한계입니다. 

 

이제 두 개의 개별 배열 인덱스를 사용해 보겠습니다. 이 쿼리를 지원하는 인덱스는 다음과 같이 보일 수 있습니다. Couchbase N1QL 인덱스 어드바이저Couchbase 6.5의 새로운 (DP) 기능입니다:

 

 

이 두 인덱스를 사용하면 쿼리는 5개의 결과(hotel_26020, hotel_10025, hotel_5081, hotel_20425, hotel_25327)와 다음 실행 계획으로 성공적으로 실행됩니다: 

그림 4 - 다중 인덱스(GSI)를 사용한 실행 계획

JSON에서도 마찬가지입니다:

 

이 예제에 사용되는 단일 노드 클러스터에서는 5개의 결과 문서를 반환하는 데 약 190-200밀리초의 쿼리 경과 시간이 소요됩니다. 계획에서 볼 수 있듯이, 우리가 만든 두 개의 배열 인덱스 각각을 사용하는 두 개의 IndexScan3 연산자가 있고, 각 인덱스 스캔 결과에 대한 DistinctScan이 있으며, 그 다음에는 UnionScan이 있습니다. UnionScan은 1646개의 문서에 대한 #itemsIn 값과 904개의 문서에 대한 #itemsOut 값을 보여주고, Fetch 연산자도 904개의 문서를 가져오며, 마지막으로 Filter 연산자를 사용하면 #ItemsOut 값 5를 얻습니다. 쿼리에서 반환된 문서가 5개라는 점을 고려하면 904개의 문서를 가져오는 것은 낭비이며, 실제로 5개만 필요한데 905개의 문서를 가져오는 데 전체 경과 시간 중 약 170밀리초가 소요됩니다.  

솔루션

반면, FTS 반전 인덱스는 여러 배열에 대해 쉽게 생성할 수 있으며 여러 배열의 필드를 검색해야 하는 경우에 적합합니다. 호텔 문서에서 public_likes 배열과 reviews 배열 내의 작성자 필드 모두에 대한 FTS 인덱스를 만들어 보겠습니다. 

 

인덱스 생성 단계: 

  1. 전체 텍스트 검색 UI에서 '색인 추가'를 클릭합니다.
  2. 인덱스 이름(예: "hotel_mult_arrays")을 지정하고 여행 샘플 버킷을 선택합니다. 
  3. 여행 샘플 버킷의 각 문서에는 문서의 유형을 나타내는 "type" 필드가 있으므로 "JSON 유형 필드"를 "type"으로 설정해 두세요.
  4. 유형 매핑 아래에서:  
    1. 모든 호텔 문서를 검색해야 하므로 "+ 유형 매핑 추가"를 클릭하고 유형 이름으로 "호텔"을 지정합니다.  
    2. 사용 가능한 분석기 목록은 유형 이름 필드 오른쪽에 있는 풀다운 메뉴를 통해 액세스할 수 있습니다. 이 사용 사례의 경우, 유형 매핑이 인덱스에서 기본 분석기를 상속하도록 '상속'을 선택한 상태로 둡니다.
    3. 호텔 공개 좋아요를 검색하고 작성자 필드를 검토해야 하므로 '지정된 필드만 색인화'를 선택합니다. 이 옵션을 선택하면 문서에서 사용자가 지정한 필드만 호텔 유형 매핑의 색인에 포함됩니다(매핑은 동적이 아니므로 모든 필드를 색인화할 수 있는 것으로 간주됩니다). 
    4. 확인을 클릭합니다.  
    5. 호텔 유형 매핑이 있는 행에 마우스를 올려놓고 + 버튼을 클릭한 다음 "하위 필드 삽입". 이렇게 하면 public_likes 배열이 인덱스에 개별적으로 포함될 수 있습니다. 다음을 지정합니다: 
      1. 필드를 클릭합니다: 색인할 필드의 이름인 'public_likes'를 입력합니다.
      2. 유형으로 설정합니다: public_likes 배열의 텍스트로 설정합니다.
      3. 로 검색할 수 있습니다: 현재 사용 사례의 필드 이름과 동일하게 유지합니다. 대체 필드 이름을 나타내는 데 사용할 수 있습니다. 
      4. 분석기를 사용합니다: 유형 매핑에서 수행한 것과 같습니다, 이 사용 사례의 경우 "상속"을 선택한 상태로 두십시오. 유형 매핑이 기본 분석기를 상속하도록 설정합니다.
      5. 색인 확인란을 선택합니다: 이 확인란을 선택해 두면 필드가 색인에 포함됩니다. 이 확인란을 선택 취소하면 색인에서 필드가 명시적으로 제거됩니다.
      6. 저장 확인란을 선택합니다: 이 설정을 선택하면 검색 결과에 필드 콘텐츠가 포함되어 결과에서 일치하는 표현식을 강조 표시할 수 있습니다. 인덱스를 테스트하는 데 유용하지만 인덱스 크기가 증가하므로 강조 표시가 필요하지 않은 경우 Prod에서는 권장되지 않습니다.
      7. "_모든 필드에 포함" 확인란을 선택합니다: 사용 사례 요구 사항이 여러 필드를 검색하는 것이므로 이 확인란을 선택된 상태로 둡니다. 
      8. "용어 벡터 포함" 체크박스를 선택합니다: 인덱스 개발 및 테스트 중에 결과를 강조 표시할 수 있도록 이 옵션도 선택된 상태로 둡니다. 
      9. 문서 값 확인란을 선택합니다: 이 설정을 선택 취소합니다. 이 설정은 필드 값을 인덱스에 저장하여 검색 패싯과 필드 값에 따른 검색 결과 정렬을 지원하지만 이 사용 사례에서는 둘 다 필요하지 않습니다. 
      10. 확인을 클릭합니다.
    6. 호텔 유형 매핑이 있는 행에 마우스를 올려놓고 + 버튼을 클릭한 다음 "자식 매핑 삽입". 이렇게 하면 리뷰 하위 문서 배열이 색인에 포함될 수 있습니다. 속성 이름 "reviews"를 입력하고, 분석기 드롭다운에서 "상속"을 선택한 상태로 두고, "지정된 필드만 색인"을 선택한 다음 확인을 클릭합니다. 
    7. 리뷰 하위 매핑이 있는 행에 마우스를 올려놓고 + 버튼을 클릭한 다음 "하위 필드 삽입". 이렇게 하면 검토 하위 문서 배열의 작성자 필드가 색인에 포함될 수 있습니다. 다음을 지정합니다: 
      1. 필드를 클릭합니다: 색인할 필드의 이름인 '작성자'를 입력합니다.
      2. 유형으로 설정합니다: 작성자 필드의 텍스트로 이 설정을 그대로 둡니다.
      3. 로 검색할 수 있습니다: 현재 사용 사례의 필드 이름과 동일하게 유지합니다. 대체 필드 이름을 나타내는 데 사용할 수 있습니다. 
      4. 분석기를 사용합니다: 유형 매핑에서 수행한 것과 같습니다, 이 사용 사례의 경우 "상속"을 선택한 상태로 두십시오. 유형 매핑이 기본 분석기를 상속하도록 설정합니다.
      5. 색인 확인란을 선택합니다: 이 확인란을 선택해 두면 필드가 색인에 포함됩니다. 이 확인란을 선택 취소하면 색인에서 필드가 명시적으로 제거됩니다.
      6. 저장 확인란을 선택합니다: 이 설정을 선택하면 검색 결과에 필드 콘텐츠가 포함되어 결과에서 일치하는 표현식을 강조 표시할 수 있습니다. 인덱스를 테스트하는 데 유용하지만 인덱스 크기가 증가하므로 강조 표시가 필요하지 않은 경우 Prod에서는 권장되지 않습니다.
      7. "_모든 필드에 포함" 확인란을 선택합니다: 사용 사례 요구 사항이 여러 필드를 검색하는 것이므로 이 확인란을 선택된 상태로 둡니다. 
      8. "용어 벡터 포함" 체크박스를 선택합니다: 인덱스 개발 및 테스트 중에 결과를 강조 표시할 수 있도록 이 옵션도 선택된 상태로 둡니다.  
      9. 문서 값 확인란을 선택합니다: 이 설정을 선택 취소합니다. 이 설정은 필드 값을 인덱스에 저장하여 검색 패싯과 필드 값에 따른 검색 결과 정렬을 지원하지만 이 사용 사례에서는 둘 다 필요하지 않습니다. 
      10. 확인을 클릭합니다.
    8. 마지막으로 '기본' 유형 매핑 옆의 확인란을 선택 취소합니다. 기본 매핑을 활성화된 상태로 두면 사용자가 적극적으로 유형 매핑을 지정했는지 여부에 관계없이 버킷의 모든 문서가 색인에 포함됩니다. 호텔 문서만 필요하며 이전에 추가한 호텔 유형 매핑에 의해 포함됩니다. 
  5. 나머지 접힌 패널(분석기, 사용자 지정 필터, 날짜/시간 파서 및 고급)은 기본값으로 충분합니다. 
  6. 인덱스 복제본은 클러스터가 n+1 노드에서 검색 서비스를 실행하는 경우 1, 2 또는 3으로 설정할 수 있습니다. 단일 노드 개발 환경에서는 기본값인 0을 유지합니다. 
  7. 인덱스 유형의 경우, 새로 생성되는 모든 인덱스에는 기본값인 "버전 6.0(Scorch)"이 적합합니다. Scorch는 디스크의 인덱스 크기를 줄이고 인덱싱 및 변경 처리를 위한 연산자 성능에서 향상된 MongoDB를 제공합니다.
  8. 인덱스 파티션은 기본값인 6으로 그대로 둘 수 있습니다. 
  9. 이 시점에서 인덱스 생성 페이지는 다음과 같이 표시되어야 합니다. 에서 캡처한 마지막 프레임 그림 5. "색인 생성"을 클릭하여 프로세스를 완료합니다. 

 

그림 5 - 다중 배열로 FTS 인덱스 만들기

 

참고: REST API를 통해 이 인덱스를 생성하는 데 사용되는 JSON 페이로드는 부록을 참조하세요.

 

인덱스에 대해 쿼리를 테스트합니다: 

  1. 전체 텍스트 검색 UI에서 인덱싱 진행률이 100%로 표시될 때까지 기다린 다음, 인덱스 이름 "hotel_mult_arrays"를 클릭합니다. 
  2. 'Ozella'라는 사용자의 좋아요 또는 후기가 있는 호텔을 검색하려면 '이 색인 검색...' 텍스트 상자에 'Ozella'를 입력한 후 검색을 클릭합니다. 색인된 두 필드가 모두 기본 필드 "_all".
  3. 결과는 (그림 6과 유사하게) 일치하는 각 문서의 키와 강조 표시된 일치 필드와 함께 표시됩니다. 반환된 문서 ID는 이전 N1QL 쿼리에서 반환된 것과 동일합니다.  

그림 6 - "Ozella"에 대한 "hotel_mult_arrays" 검색 결과 색인화

 

이것은 2개의 배열 키에 대한 단일 인덱스이며, 앞서 언급했듯이 b-트리 기반 인덱스에서는 절대 할 수 없는 작업입니다. 이제 SEARCH() 함수를 사용하여 N1QL 쿼리에서 이 FTS 인덱스를 활용해 보겠습니다. 쿼리는 다음과 같이 보일 수 있습니다: 

 

쿼리에 대해 몇 가지 주의해야 할 사항이 있습니다: 

  • USE INDEX...USING FTS 절은 GSI 인덱스가 아닌 FTS 인덱스를 사용하도록 지정하므로 이 쿼리는 인덱스 서비스를 사용하지 않습니다. (문서)
  • FTS 인덱스는 사용자 지정 유형 매핑을 사용하므로 쿼리에는 WHERE 절에 일치하는 유형이 지정되어 있어야 합니다(t.type="hotel").  
  • FTS 인덱스 이름은 SEARCH() 함수의 "index" 필드에 힌트로 지정되지만 USE INDEX 절이 "index" 필드에 제공된 힌트보다 우선하므로 이는 선택 사항입니다. (문서)  

생성한 FTS 인덱스를 사용하여 N1QL 쿼리가 성공적으로 실행되고 5개의 결과(hotel_5081, hotel_26020, hotel_10025, hotel_20425, hotel_25327)와 다음 실행 계획을 반환합니다: 

그림 7 - 다중 인덱스(FTS)를 사용한 실행 계획

JSON에서도 마찬가지입니다:

 

이 예제에 사용되는 단일 노드 클러스터에서는 동일한 5개의 문서를 반환하는 데 쿼리 경과 시간이 약 20밀리초입니다. 계획에서 볼 수 있듯이 IndexFtsSearch 연산자는 있지만 IndexScan3, DistinctScan, UnionScan 또는 IntersectScan 연산자는 없습니다. 이러한 고가의 GSI 연산자가 없으면 전체 쿼리가 훨씬 더 효율적입니다. IndexFtsSearch 연산자는 FTS 인덱스에서 일치하는 문서 5개를 Fetch 연산자에게 보내면 이 5개의 문서만 가져옵니다. 여기서는 5개의 문서와 904개의 문서만 가져오기 때문에 이전 쿼리보다 훨씬 효율적이며, 이는 전체 경과 시간(및 가져오기 연산자의 servTime)을 비교해도 확인할 수 있습니다: 쿼리 1에서 170ms, 쿼리 2에서 1.5ms) 비교에서도 확인할 수 있습니다.  

 

결론

GSI에서는 단일 쿼리에서 여러 배열 인덱스를 혼합하여 일치시킬 수 있지만, FTS에서는 단일 FTS 인덱스에서 여러 배열을 혼합하여 일치시킬 수 있습니다(그리고 FTS에서는 인덱스의 필드 순서와 관련하여 GSI에서처럼 선행 키 문제가 없습니다). 호텔 문서에서 2개의 배열을 쿼리하는 이 간단한 예제에서 보았듯이, N1QL의 새로운 SEARCH() 함수를 사용하면 더 간단하고 성능이 뛰어난 배열 쿼리를 수행할 수 있습니다. 여러 개의 배열을 사용하는 쿼리에도 동일한 개념을 적용할 수 있으며, 이 경우 여러 GSI 배열 인덱스를 사용하는 N1QL 쿼리에 비해 훨씬 더 유리한 결과를 얻을 수 있습니다. 이 접근 방식은 더 적은 시스템 리소스를 사용하고 더 높은 처리량을 제공하므로 전반적인 시스템 효율성이 향상됩니다.  

이는 N1QL과 FTS 통합의 장점 중 한 가지 예일 뿐이며, 다른 장점은 아래 참고 섹션의 블로그 게시물에 자세히 설명되어 있습니다. 

 

참조

 

부록

인덱스 정의 JSON: hotel_mult_arrays

 

 

이 문서 공유하기
받은 편지함에서 카우치베이스 블로그 업데이트 받기
이 필드는 필수 입력 사항입니다.

작성자

게시자 Brian Kane, 솔루션 엔지니어, Couchbase

Brian Kane은 Couchbase의 솔루션 엔지니어로 1996년부터 애플리케이션 개발 및 데이터베이스 기술 분야에서 일하고 있습니다. 현재 텍사스주 휴스턴에 거주하고 있습니다.

댓글 남기기

카우치베이스 카펠라를 시작할 준비가 되셨나요?

구축 시작

개발자 포털에서 NoSQL을 살펴보고, 리소스를 찾아보고, 튜토리얼을 시작하세요.

카펠라 무료 사용

클릭 몇 번으로 Couchbase를 직접 체험해 보세요. Capella DBaaS는 가장 쉽고 빠르게 시작할 수 있는 방법입니다.

연락하기

카우치베이스 제품에 대해 자세히 알고 싶으신가요? 저희가 도와드리겠습니다.