밀버스 엔그램 인덱스를 소개합니다: 에이전트 워크로드를 위한 더 빠른 키워드 매칭 및 '좋아요' 쿼리
상담원 시스템에서 컨텍스트 검색은 전체 파이프라인의 기본 구성 요소로, 다운스트림 추론, 계획 및 조치를 위한 기반을 제공합니다. 벡터 검색은 상담원이 대규모의 비정형 데이터 세트에서 의도와 의미를 파악하는 의미론적으로 관련성 있는 컨텍스트를 검색하는 데 도움이 됩니다. 하지만 의미론적 연관성만으로는 충분하지 않은 경우가 많습니다. 상담원 파이프라인은 또한 제품 이름, 함수 호출, 오류 코드 또는 법적으로 중요한 용어와 같은 정확한 키워드 제약 조건을 적용하기 위해 전체 텍스트 검색에 의존합니다. 이 지원 계층은 검색된 컨텍스트가 관련성이 있을 뿐만 아니라 하드 텍스트 요구 사항을 명시적으로 충족하도록 보장합니다.
실제 워크로드는 이러한 요구 사항을 일관되게 반영합니다:
고객 지원 도우미는 특정 제품이나 성분이 언급된 대화를 찾아야 합니다.
코딩 코파일럿은 정확한 함수 이름, API 호출 또는 오류 문자열이 포함된 스니펫을 찾습니다.
법률, 의료 및 학술 상담원은 문서에서 반드시 그대로 표시되어야 하는 조항이나 인용문을 필터링합니다.
기존에는 시스템에서 SQL LIKE 연산자를 사용하여 이 작업을 처리했습니다. name LIKE '%rod%' 같은 쿼리는 간단하고 광범위하게 지원되지만, 동시성이 높고 데이터 양이 많은 경우 이러한 단순성은 상당한 성능 비용을 수반합니다.
인덱스가 없는
LIKE쿼리는 전체 컨텍스트 저장소를 스캔하여 행별로 패턴 매칭을 적용합니다. 수백만 개의 레코드가 있는 경우 단일 쿼리에도 몇 초가 걸릴 수 있으며, 이는 실시간 상담원 상호 작용에 비해 너무 느립니다.기존의 역 인덱스를 사용하더라도
%rod%와 같은 와일드카드 패턴은 엔진이 여전히 전체 사전을 탐색하고 각 항목에서 패턴 일치를 실행해야 하기 때문에 최적화하기 어렵습니다. 이 작업은 행 스캔을 피할 수 있지만 근본적으로 선형적이기 때문에 개선 효과가 미미합니다.
이는 하이브리드 검색 시스템에서 분명한 차이를 만들어냅니다. 벡터 검색은 의미론적 연관성을 효율적으로 처리하지만, 정확한 키워드 필터링은 종종 파이프라인에서 가장 느린 단계가 됩니다.
Milvus는 기본적으로 메타데이터 필터링을 통해 하이브리드 벡터 및 전체 텍스트 검색을 지원합니다. 키워드 매칭의 한계를 해결하기 위해 Milvus는 텍스트를 작은 하위 문자열로 분할하고 효율적인 조회를 위해 색인화하여 LIKE 성능을 개선하는 Ngram Index를 도입했습니다. 이를 통해 쿼리 실행 중에 검사하는 데이터의 양을 획기적으로 줄여 실제 에이전트 워크로드에서 수십에서 수백 배 빠른 LIKE 쿼리를 제공할 수 있습니다.
이 글의 나머지 부분에서는 Milvus에서 Ngram Index가 어떻게 작동하는지 살펴보고 실제 시나리오에서 그 성능을 평가합니다.
Ngram 인덱스란 무엇인가요?
데이터베이스에서 텍스트 필터링은 일반적으로 데이터를 검색하고 관리하는 데 사용되는 표준 쿼리 언어인 SQL을 사용하여 표현됩니다. 가장 널리 사용되는 텍스트 연산자 중 하나는 패턴 기반 문자열 일치를 지원하는 LIKE 입니다.
LIKE 표현식은 와일드카드 사용 방식에 따라 크게 네 가지 일반적인 패턴 유형으로 분류할 수 있습니다:
접두사 일치 (
name LIKE '%rod%'): 하위 문자열 막대가 텍스트의 아무 곳에나 나타나는 레코드와 일치시킵니다.접두사 일치 (
name LIKE 'rod%'): 텍스트가 rod로 시작하는 레코드를 일치시킵니다.접미사 일치 (
name LIKE '%rod'): 텍스트가 rod로 끝나는 레코드를 일치시킵니다.와일드카드 일치 (
name LIKE '%rod%aab%bc_de'): 여러 하위 문자열 조건(%)과 단일 문자 와일드카드(_)를 단일 패턴으로 결합합니다.
이러한 패턴은 모양과 표현 방식이 다르지만 Milvus의 Ngram 인덱스는 동일한 기본 접근 방식을 사용하여 모든 패턴을 가속화합니다.
인덱스를 구축하기 전에 Milvus는 각 텍스트 값을 n-그램이라고 하는 고정된 길이의 짧고 겹치는 하위 문자열로 분할합니다. 예를 들어, n = 3인 경우, "Milvus "라는 단어는 다음과 같은 3그램으로 분해됩니다: "Mil", "ilv", "lvu", "vus". 그런 다음 각 n-그램은 하위 문자열을 해당 문자열이 나타나는 문서 ID 집합에 매핑하는 역 인덱스에 저장됩니다. 쿼리 시, LIKE 조건은 n-그램 조회의 조합으로 변환되어 Milvus가 대부분의 일치하지 않는 레코드를 빠르게 필터링하고 훨씬 더 작은 후보 세트에 대해 패턴을 평가할 수 있게 해줍니다. 이것이 바로 값비싼 문자열 스캔을 효율적인 인덱스 기반 쿼리로 바꾸는 것입니다.
min_gram 와 max_gram 라는 두 개의 매개변수가 Ngram 인덱스의 구성 방식을 제어합니다. 이 두 매개변수는 Milvus가 생성하고 색인하는 하위 문자열 길이의 범위를 정의합니다.
min_gram: 인덱싱할 최단 부분 문자열 길이. 실제로, 이것은 또한 Ngram 인덱스의 혜택을 받을 수 있는 최소 쿼리 부분 문자열 길이를 설정합니다.max_gram: 인덱싱할 가장 긴 부분 문자열 길이. 쿼리 시에는 더 긴 쿼리 문자열을 N그램으로 분할할 때 사용되는 최대 창 크기를 추가로 결정합니다.
밀버스는 길이가 min_gram 와 max_gram 사이에 속하는 모든 인접한 하위 문자열을 색인함으로써 지원되는 모든 LIKE 패턴 유형을 가속화하기 위한 일관되고 효율적인 기반을 구축합니다.
Ngram 인덱스는 어떻게 작동하나요?
Milvus는 2단계 프로세스로 Ngram 인덱스를 구현합니다:
인덱스를 구축합니다: 데이터 수집 중에 각 문서에 대해 n-그램을 생성하고 역 인덱스를 구축합니다.
쿼리 가속화: 인덱스를 사용하여 검색 범위를 작은 후보 집합으로 좁힌 다음, 그 후보 집합에서 정확히 일치하는
LIKE을 확인합니다.
구체적인 예시를 통해 이 프로세스를 더 쉽게 이해할 수 있습니다.
1단계: 색인 구축
텍스트를 n-그램으로 분해합니다:
다음 설정으로 "Apple"이라는 텍스트를 색인한다고 가정해 보겠습니다:
min_gram = 2max_gram = 3
이 설정에서 Milvus는 길이 2와 3의 연속된 모든 하위 문자열을 생성합니다:
2그램
Ap,pp,pl,le3-grams:
App,ppl,ple
역 인덱스를 구축합니다:
이제 5개의 레코드로 구성된 작은 데이터 세트를 생각해 봅시다:
문서 0:
Apple문서 1:
Pineapple문서 2:
Maple문서 3:
Apply문서 4:
Snapple
수집하는 동안 Milvus는 각 레코드에 대해 n-그램을 생성하고 이를 반전된 인덱스에 삽입합니다. 이 인덱스에서
키는 n-그램(하위 문자열)입니다.
값은 n-그램이 나타나는 문서 ID의 목록입니다.
"Ap" -> [0, 3]
"App" -> [0, 3]
"Ma" -> [2]
"Map" -> [2]
"Pi" -> [1]
"Pin" -> [1]
"Sn" -> [4]
"Sna" -> [4]
"ap" -> [1, 2, 4]
"apl" -> [2]
"app" -> [1, 4]
"ea" -> [1]
"eap" -> [1]
"in" -> [1]
"ine" -> [1]
"le" -> [0, 1, 2, 4]
"ly" -> [3]
"na" -> [4]
"nap" -> [4]
"ne" -> [1]
"nea" -> [1]
"pl" -> [0, 1, 2, 3, 4]
"ple" -> [0, 1, 2, 4]
"ply" -> [3]
"pp" -> [0, 1, 3, 4]
"ppl" -> [0, 1, 3, 4]
이제 인덱스가 완전히 구축되었습니다.
2단계: 쿼리 가속화
LIKE 필터가 실행되면 Milvus는 다음 단계를 통해 N그램 인덱스를 사용하여 쿼리 평가 속도를 높입니다:
1. 쿼리 용어를 추출합니다: LIKE 표현식에서 와일드카드가 없는 연속된 하위 문자열을 추출합니다(예: '%apple%' 은 apple 이 됩니다).
2. 쿼리 용어 분해하기: 쿼리 용어는 길이(L)와 설정된 min_gram 및 max_gram 을 기준으로 n-그램으로 분해됩니다.
3. 각 그램 찾기 및 교차: Milvus는 역 인덱스에서 쿼리 n-그램을 찾아 문서 ID 목록을 교차하여 작은 후보 집합을 생성합니다.
4. 결과를 확인하고 반환합니다: 원래 LIKE 조건은 이 후보 집합에만 적용되어 최종 결과를 결정합니다.
실제로 쿼리가 n-그램으로 분할되는 방식은 패턴 자체의 형태에 따라 달라집니다. 이것이 어떻게 작동하는지 알아보기 위해 접두사 일치와 와일드카드 일치라는 두 가지 일반적인 경우에 초점을 맞춰 보겠습니다. 접두사 및 접미사 일치는 접두사 일치와 동일하게 작동하므로 별도로 다루지 않겠습니다.
접두사 일치
접미사 일치의 경우 실행은 min_gram 및 max_gram 에 대한 리터럴 하위 문자열(L)의 길이에 따라 달라집니다.
min_gram ≤ L ≤ max_gram (예: strField LIKE '%ppl%')
리터럴 부분 문자열 ppl 은 전적으로 구성된 n-그램 범위 내에 있습니다. Milvus는 반전된 인덱스에서 n-그램 "ppl" 을 직접 조회하여 후보 문서 ID [0, 1, 3, 4] 를 생성합니다.
리터럴 자체가 인덱싱된 n-그램이기 때문에 모든 후보가 이미 접미사 조건을 만족합니다. 최종 검증 단계에서는 어떤 레코드도 제거되지 않으며 결과는 [0, 1, 3, 4] 로 유지됩니다.
L > max_gram (예: strField LIKE '%pple%')
리터럴 하위 문자열 pple 은 max_gram 보다 길기 때문에 창 크기 max_gram 를 사용하여 겹치는 n-그램으로 분해됩니다. max_gram = 3 을 사용하면 n-그램 "ppl" 과 "ple" 이 생성됩니다.
Milvus는 반전된 인덱스에서 각 n-그램을 조회합니다:
"ppl"→[0, 1, 3, 4]"ple"→[0, 1, 2, 4]
이 목록을 교차하면 후보 집합 [0, 1, 4] 이 생성됩니다. 그런 다음 원래의 LIKE '%pple%' 필터가 이 후보에 적용됩니다. 세 가지 모두 조건을 만족하므로 최종 결과는 [0, 1, 4] 로 유지됩니다.
L < min_gram (예: strField LIKE '%pp%')
리터럴 하위 문자열은 min_gram 보다 짧기 때문에 인덱싱된 N그램으로 분해할 수 없습니다. 이 경우 N그램 인덱스를 사용할 수 없으며 Milvus는 기본 실행 경로로 돌아가서 패턴 일치를 통해 전체 스캔을 통해 LIKE 조건을 평가합니다.
와일드카드 일치 (예: strField LIKE '%Ap%pple%')
이 패턴에는 여러 와일드카드가 포함되어 있으므로 Milvus는 먼저 이 패턴을 연속된 리터럴인 "Ap" 과 "pple" 으로 분할합니다.
그런 다음 Milvus는 각 리터럴을 독립적으로 처리합니다:
"Ap"는 길이가 2이고 n-그램 범위에 속합니다."pple"는max_gram보다 길고"ppl"과"ple"로 분해됩니다.
이렇게 하면 쿼리가 다음과 같은 n-그램으로 줄어듭니다:
"Ap"→[0, 3]"ppl"→[0, 1, 3, 4]"ple"→[0, 1, 2, 4]
이 목록들을 교차하면 단일 후보인 [0] 가 생성됩니다.
마지막으로 원본 LIKE '%Ap%pple%' 필터가 문서 0("Apple")에 적용됩니다. 전체 패턴을 만족시키지 못하므로 최종 결과 세트는 비어 있습니다.
Ngram 인덱스의 한계와 장단점
Ngram 인덱스는 LIKE 쿼리 성능을 크게 향상시킬 수 있지만, 실제 배포 시 고려해야 할 장단점이 있습니다.
- 인덱스 크기 증가
Ngram 인덱스의 주요 비용은 스토리지 오버헤드 증가입니다. 인덱스는 길이가 min_gram 과 max_gram 사이에 있는 모든 인접한 하위 문자열을 저장하기 때문에 이 범위가 확장됨에 따라 생성되는 n-그램의 수가 빠르게 증가합니다. n그램 길이가 추가될 때마다 모든 텍스트 값에 대해 겹치는 하위 문자열의 전체 집합이 하나 더 추가되므로 인덱스 키와 해당 게시 목록의 수가 모두 증가합니다. 실제로 범위를 한 글자만 확장하면 표준 반전 인덱스에 비해 인덱스 크기가 대략 두 배가 될 수 있습니다.
- 모든 워크로드에 효과적이지 않음
Ngram 인덱스가 모든 워크로드를 가속화하지는 않습니다. 쿼리 패턴이 매우 불규칙하거나, 매우 짧은 리터럴을 포함하거나, 필터링 단계에서 데이터 세트를 작은 후보 집합으로 줄이는 데 실패하면 성능 이점이 제한될 수 있습니다. 이러한 경우, 인덱스가 존재하더라도 쿼리 실행 비용이 전체 스캔 비용에 근접할 수 있습니다.
'좋아요' 쿼리에서 Ngram 인덱스 성능 평가하기
이 벤치마크의 목표는 Ngram 인덱스가 실제로 LIKE 쿼리를 얼마나 효과적으로 가속하는지 평가하는 것입니다.
테스트 방법론
성능을 맥락에 맞게 설명하기 위해 두 가지 기준 실행 모드와 비교합니다:
마스터: 인덱스 없이 무차별 실행.
마스터 반전: 기존의 반전된 인덱스를 사용한 실행.
서로 다른 데이터 특성을 다루기 위해 두 가지 테스트 시나리오를 설계했습니다:
위키 텍스트 데이터 세트: 100,000개의 행, 각 텍스트 필드가 1KB로 잘린 경우.
단일 단어 데이터 세트: 1,000,000개의 행, 각 행에 단일 단어가 포함됨.
두 시나리오 모두에 걸쳐 다음 설정이 일관되게 적용됩니다:
쿼리는 접미사 일치 패턴을 사용합니다(
%xxx%).Ngram 인덱스는
min_gram = 2및max_gram = 4쿼리 실행 비용을 분리하고 결과 구체화 오버헤드를 피하기 위해 모든 쿼리는 전체 결과 집합 대신
count(*)을 반환합니다.
결과
위키에 대한 테스트, 각 줄은 콘텐츠 길이가 1000으로 잘린 100K 행의 위키 텍스트입니다.
| 리터럴 | 시간(ms) | 속도 향상 | Count | |
|---|---|---|---|---|
| 마스터 | 경기장 | 207.8 | 335 | |
| 마스터 반전 | 2095 | 335 | ||
| Ngram | 1.09 | 190 / 1922 | 335 | |
| 마스터 | 중등 학교 | 204.8 | 340 | |
| 마스터-반전 | 2000 | 340 | ||
| N그램 | 1.26 | 162.5 / 1587 | 340 | |
| Master | 남녀 공학, 중등 학교 스폰서입니다. | 223.9 | 1 | |
| 마스터 반전 | 2100 | 1 | ||
| N그램 | 1.69 | 132.5 / 1242.6 | 1 |
단일 단어, 1M 행에 대한 테스트
| 리터럴 | 시간(ms) | 속도 향상 | Count | |
|---|---|---|---|---|
| 마스터 | na | 128.6 | 40430 | |
| 마스터 반전 | 66.5 | 40430 | ||
| Ngram | 1.38 | 93.2 / 48.2 | 40430 | |
| Master | nat | 122 | 5200 | |
| 마스터 인버트 | 65.1 | 5200 | ||
| Ngram | 1.27 | 96 / 51.3 | 5200 | |
| Master | nati | 118.8 | 1630 | |
| 마스터 반전 | 66.9 | 1630 | ||
| Ngram | 1.21 | 98.2 / 55.3 | 1630 | |
| Master | natio | 118.4 | 1100 | |
| 마스터 인버티드 | 65.1 | 1100 | ||
| N그램 | 1.33 | 89 / 48.9 | 1100 | |
| 마스터 | 국가 | 118 | 1100 | |
| 마스터 반전 | 63.3 | 1100 | ||
| Ngram | 1.4 | 84.3 / 45.2 | 1100 |
참고: 이 결과는 5월에 실시한 벤치마크를 기반으로 합니다. 그 이후로 마스터 브랜치는 추가적인 성능 최적화를 거쳤으므로 현재 버전에서는 여기서 관찰된 성능 격차가 더 줄어들 것으로 예상됩니다.
벤치마크 결과에서 분명한 패턴을 확인할 수 있습니다. Ngram 인덱스는 모든 경우에서 좋아요 쿼리를 크게 가속화하며, 쿼리 실행 속도는 기본 텍스트 데이터의 구조와 길이에 따라 크게 달라집니다.
1,000바이트로 잘린 위키 스타일 문서와 같이 긴 텍스트 필드의 경우 특히 성능 향상이 두드러집니다. 인덱스가 없는 무차별 대입 실행과 비교했을 때, Ngram 인덱스는 약 100~200배의 속도 향상을 달성합니다. 기존의 역 인덱스와 비교하면 1,200-1,900배에 이르는 훨씬 더 극적인 개선이 이루어집니다. 이는 긴 텍스트에 대한 '좋아요' 쿼리가 기존 인덱싱 접근 방식에서 특히 비용이 많이 드는 반면, n-그램 조회는 검색 공간을 매우 작은 후보 집합으로 빠르게 좁힐 수 있기 때문입니다.
단일 단어 항목으로 구성된 데이터 세트에서는 이득이 더 작지만 여전히 상당합니다. 이 시나리오에서 Ngram 인덱스는 무차별 대입 실행보다 약 80-100배, 기존 역 인덱스보다 45-55배 더 빠르게 실행됩니다. 짧은 텍스트는 본질적으로 스캔 비용이 더 저렴하지만, N그램 기반 접근 방식은 여전히 불필요한 비교를 피하고 쿼리 비용을 지속적으로 줄여줍니다.
결론
N그램 인덱스는 텍스트를 고정 길이의 n그램으로 나누고 반전된 구조를 사용하여 색인을 생성함으로써 LIKE 쿼리를 가속화합니다. 이 설계는 비용이 많이 드는 하위 문자열 매칭을 최소한의 검증을 거친 효율적인 n-그램 조회로 전환합니다. 그 결과, LIKE 의 정확한 의미는 유지하면서 전체 텍스트 스캔은 피할 수 있습니다.
실제로 이 접근 방식은 광범위한 워크로드에 걸쳐 효과적이며, 특히 긴 텍스트 필드에서 퍼지 매칭에 대해 강력한 결과를 제공합니다. 따라서 Ngram 인덱스는 코드 검색, 고객 지원 상담원, 법률 및 의료 문서 검색, 기업 지식 기반, 학술 검색과 같이 정확한 키워드 매칭이 필수적인 실시간 시나리오에 적합합니다.
동시에, Ngram 인덱스는 신중한 구성을 통해 이점을 얻을 수 있습니다. 적절한 min_gram 및 max_gram 값을 선택하는 것은 인덱스 크기와 쿼리 성능의 균형을 맞추는 데 매우 중요합니다. 실제 쿼리 패턴을 반영하도록 조정할 경우, Ngram Index는 운영 시스템에서 고성능 LIKE 쿼리를 위한 실용적이고 확장 가능한 솔루션을 제공합니다.
Ngram 인덱스에 대한 자세한 내용은 아래 문서를 참조하세요:
최신 Milvus의 기능에 대해 궁금한 점이 있거나 자세히 알아보고 싶으신가요? Discord 채널에 참여하거나 GitHub에 이슈를 제출하세요. 또한 Milvus 오피스 아워를 통해 20분간의 일대일 세션을 예약하여 인사이트, 안내 및 질문에 대한 답변을 얻을 수 있습니다.
Milvus 2.6 기능에 대해 자세히 알아보기
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.
Get StartedLike the article? Spread the word



