Представляем индекс Milvus Ngram: Ускоренное сопоставление ключевых слов и LIKE-запросы для агентских рабочих нагрузок
В агентных системах поиск контекста является основополагающим строительным блоком для всего конвейера, обеспечивая основу для последующих рассуждений, планирования и действий. Векторный поиск помогает агентам извлекать семантически релевантный контекст, отражающий намерения и смысл в больших и неструктурированных наборах данных. Однако одной лишь семантической релевантности зачастую недостаточно. Агентские конвейеры также полагаются на полнотекстовый поиск для обеспечения точных ограничений на ключевые слова - например, названия продуктов, вызовы функций, коды ошибок или юридически значимые термины. Этот вспомогательный слой гарантирует, что найденный контекст не только релевантен, но и явно удовлетворяет жестким текстовым требованиям.
Реальные рабочие нагрузки постоянно отражают эту потребность:
Ассистенты службы поддержки клиентов должны найти разговоры, в которых упоминается конкретный продукт или ингредиент.
Кодировщики ищут фрагменты, содержащие точное имя функции, вызов API или строку ошибки.
Юридические, медицинские и научные агенты фильтруют документы на предмет фрагментов или цитат, которые должны быть дословными.
Традиционно системы справляются с этой задачей с помощью оператора SQL LIKE. Такой запрос, как name LIKE '%rod%', прост и широко поддерживается, но при высоком параллелизме и больших объемах данных эта простота влечет за собой значительные издержки производительности.
Без индекса запрос
LIKEсканирует все контекстное хранилище и применяет сопоставление шаблонов строка за строкой. При миллионах записей даже один запрос может занять несколько секунд - слишком медленно для взаимодействия с агентами в реальном времени.Даже с обычным инвертированным индексом шаблоны с подстановочными знаками, такие как
%rod%, по-прежнему трудно оптимизировать, поскольку движок должен просматривать весь словарь и выполнять сопоставление шаблонов по каждой записи. Эта операция позволяет избежать сканирования строк, но остается принципиально линейной, что приводит лишь к незначительным улучшениям.
Это создает явный пробел в гибридных поисковых системах: векторный поиск эффективно справляется с семантической релевантностью, но фильтрация по точным ключевым словам часто становится самым медленным шагом в конвейере.
Milvus поддерживает гибридный векторный и полнотекстовый поиск с фильтрацией метаданных. Для устранения ограничений, связанных с подбором ключевых слов, в Milvus реализован индекс Ngram, который повышает производительность LIKE за счет разбиения текста на небольшие подстроки и их индексации для эффективного поиска. Это значительно сокращает объем данных, просматриваемых во время выполнения запроса, обеспечивая в десятки и сотни раз более высокую скорость выполнения запросов LIKE в реальных агентурных рабочих нагрузках.
В этой статье мы рассмотрим, как работает индекс Ngram в Milvus, и оценим его производительность в реальных сценариях.
Что такое индекс Ngram?
В базах данных фильтрация текста обычно выражается с помощью SQL, стандартного языка запросов, используемого для получения и управления данными. Одним из наиболее распространенных текстовых операторов в нем является LIKE, который поддерживает сопоставление строк на основе шаблонов.
Выражения LIKE можно разделить на четыре типа в зависимости от того, как используются подстановочные знаки:
Инфиксное соответствие (
name LIKE '%rod%'): Совпадает с записями, в которых подстрочный стержень встречается в любом месте текста.Префиксное совпадение (
name LIKE 'rod%'): Ищет записи, текст которых начинается с rod.Суффиксное совпадение (
name LIKE '%rod'): Искать записи, текст которых заканчивается на rod.Wildcard match (
name LIKE '%rod%aab%bc_de'): Комбинирует несколько условий подстроки (%) с односимвольными символами подстановки (_) в одном шаблоне.
Хотя эти шаблоны отличаются по внешнему виду и выразительности, индекс Ngram в Milvus ускоряет их все, используя один и тот же базовый подход.
Перед построением индекса Milvus разбивает каждое текстовое значение на короткие, перекрывающиеся подстроки фиксированной длины, называемые n-граммами. Например, при n = 3 слово "Milvus" разлагается на следующие три грамма: "Mil", "ilv", "lvu" и "vus". Каждая n-грамма хранится в инвертированном индексе, который сопоставляет подстроку с набором идентификаторов документов, в которых она встречается. Во время запроса условия LIKE преобразуются в комбинации поиска n-грамм, что позволяет Milvus быстро отфильтровать большинство несовпадающих записей и оценить шаблон по гораздо меньшему набору кандидатов. Именно это превращает дорогостоящее сканирование строк в эффективные запросы на основе индекса.
Два параметра управляют тем, как строится индекс Ngram: min_gram и max_gram. Вместе они определяют диапазон длин подстрок, которые Milvus генерирует и индексирует.
min_gram: Наименьшая длина подстроки для индексирования. На практике это также задает минимальную длину подстроки запроса, при которой может быть использован индекс Ngrammax_gram: Самая длинная длина подстроки для индексирования. Во время запроса он дополнительно определяет максимальный размер окна, используемого при разбиении длинных строк запроса на n-граммы.
Индексируя все смежные подстроки, длина которых находится в диапазоне от min_gram до max_gram, Milvus создает последовательную и эффективную основу для ускорения всех поддерживаемых типов шаблонов LIKE.
Как работает индекс Ngram?
Milvus реализует индекс Ngram в двухфазном процессе:
Построение индекса: Генерировать n-граммы для каждого документа и строить инвертированный индекс во время приема данных.
Ускорение запросов: Используйте индекс для сужения поиска до небольшого набора кандидатов, а затем проверяйте точные совпадения
LIKEпо этим кандидатам.
На конкретном примере этот процесс легче понять.
Этап 1: Создание индекса
Разложите текст на n-граммы:
Предположим, что мы индексируем текст "Apple" со следующими настройками:
min_gram = 2max_gram = 3
При этих настройках Milvus генерирует все смежные подстроки длиной 2 и 3:
2-граммы:
Ap,pp,pl,le3-граммы:
App,ppl,ple
Построение инвертированного индекса:
Теперь рассмотрим небольшой набор данных из пяти записей:
Документ 0:
AppleДокумент 1:
PineappleДокумент 2:
MapleДокумент 3:
ApplyДокумент 4:
Snapple
Во время обработки Milvus генерирует n-граммы для каждой записи и вставляет их в инвертированный индекс. В этом индексе:
Ключи - это n-граммы (подстроки).
Значения - списки идентификаторов документов, в которых встречается n-грамма.
"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 использует индекс нграмм для ускорения обработки запросов, выполняя следующие действия:
1. Извлечение термина запроса: Из выражения LIKE извлекаются смежные подстроки без подстановочных знаков (например, '%apple%' становится apple).
2. Декомпозиция термина запроса: Термин запроса декомпозируется на n-граммы с учетом его длины (L) и конфигурации min_gram и max_gram.
3. Поиск каждой граммы и пересечение: Milvus ищет n-граммы запроса в инвертированном индексе и пересекает их списки идентификаторов документов, чтобы получить небольшой набор кандидатов.
4. Проверка и возврат результатов: Оригинальное условие LIKE применяется только к этому набору кандидатов для определения окончательного результата.
На практике способ разбиения запроса на n-граммы зависит от формы самого шаблона. Чтобы понять, как это работает, мы рассмотрим два распространенных случая: инфиксные совпадения и совпадения с подстановочными знаками. Префиксные и суффиксные совпадения ведут себя так же, как и инфиксные, поэтому мы не будем рассматривать их отдельно.
Инфиксное соответствие
При инфиксном совпадении выполнение зависит от длины литеральной подстроки (L) относительно min_gram и max_gram.
1. min_gram ≤ L ≤ max_gram (например, strField LIKE '%ppl%')
Буквенная подстрока ppl полностью попадает в заданный диапазон n-грамм. Milvus напрямую ищет n-грамму "ppl" в инвертированном индексе, получая идентификаторы документов-кандидатов [0, 1, 3, 4].
Поскольку литерал сам по себе является индексированной n-граммой, все кандидаты уже удовлетворяют условию инфикса. Заключительный шаг проверки не удаляет ни одной записи, и в результате остается [0, 1, 3, 4].
2. L > max_gram (например, strField LIKE '%pple%')
Буквенная подстрока pple длиннее, чем max_gram, поэтому она декомпозируется на перекрывающиеся n-граммы с помощью окна размером max_gram. С 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].
3. L < min_gram (например, strField LIKE '%pp%')
Буквальная подстрока короче, чем min_gram, и поэтому не может быть разложена на индексированные n-граммы. В этом случае индекс Ngram не может быть использован, и 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 на LIKE-запросах
Цель этого бенчмарка - оценить, насколько эффективно индекс Ngram ускоряет выполнение запросов LIKE на практике.
Методология тестирования
Чтобы оценить его производительность в контексте, мы сравниваем его с двумя базовыми режимами выполнения:
Master: Грубое выполнение без индекса.
Master-inverted: Выполнение с использованием обычного инвертированного индекса.
Мы разработали два тестовых сценария, чтобы охватить различные характеристики данных:
Набор текстовых данных Wiki: 100 000 строк, каждое текстовое поле усечено до 1 КБ.
Набор данных с одним словом: 1 000 000 строк, где каждая строка содержит одно слово.
В обоих сценариях последовательно применяются следующие настройки:
В запросах используется инфиксный шаблон соответствия (
%xxx%).Индекс Ngram настроен на
min_gram = 2иmax_gram = 4Чтобы изолировать стоимость выполнения запроса и избежать накладных расходов на материализацию результатов, все запросы возвращают
count(*)вместо полных наборов результатов.
Результаты
Тест для вики, каждая строка - вики-текст с длиной содержимого, усеченной на 1000, 100K строк
| Буквальный | Время (мс) | Ускорение | Счетчик | |
|---|---|---|---|---|
| Мастер | стадион | 207.8 | 335 | |
| Мастер-инверсия | 2095 | 335 | ||
| Нграмма | 1.09 | 190 / 1922 | 335 | |
| Мастер | средняя школа | 204.8 | 340 | |
| Мастер-инверсия | 2000 | 340 | ||
| Нграмма | 1.26 | 162.5 / 1587 | 340 | |
| Мастер | совместное обучение, средняя школа-спонсор | 223.9 | 1 | |
| Мастер-инверсия | 2100 | 1 | ||
| Ngram | 1.69 | 132.5 / 1242.6 | 1 |
Тест для отдельных слов, 1M строк
| Букварь | Время (мс) | Ускорение | Счет | |
|---|---|---|---|---|
| Мастер | na | 128.6 | 40430 | |
| Мастер-инвертированный | 66.5 | 40430 | ||
| Ngram | 1.38 | 93.2 / 48.2 | 40430 | |
| Мастер | nat | 122 | 5200 | |
| Мастер-инверсия | 65.1 | 5200 | ||
| Нграмма | 1.27 | 96 / 51.3 | 5200 | |
| Мастер | нати | 118.8 | 1630 | |
| Мастер-инвертированный | 66.9 | 1630 | ||
| Ngram | 1.21 | 98.2 / 55.3 | 1630 | |
| Мастер | natio | 118.4 | 1100 | |
| Мастер-инвертированный | 65.1 | 1100 | ||
| Ngram | 1.33 | 89 / 48.9 | 1100 | |
| Мастер | нация | 118 | 1100 | |
| Инвертированный хозяин | 63.3 | 1100 | ||
| Ngram | 1.4 | 84.3 / 45.2 | 1100 |
Примечание: Эти результаты основаны на бенчмарках, проведенных в мае. С тех пор в ветке Master были проведены дополнительные оптимизации производительности, поэтому ожидается, что в текущих версиях разрыв в производительности, наблюдаемый здесь, будет меньше.
Результаты бенчмарков выявили четкую закономерность: индекс Ngram значительно ускоряет выполнение запросов LIKE во всех случаях, причем скорость выполнения запросов сильно зависит от структуры и длины исходных текстовых данных.
Для длинных текстовых полей, таких как документы в стиле Вики, усеченные до 1 000 байт, прирост производительности особенно заметен. По сравнению с грубым выполнением без индекса, индекс Ngram обеспечивает ускорение примерно на 100-200×. Если сравнивать с обычным инвертированным индексом, то улучшение еще более значительное и достигает 1 200-1 900×. Это объясняется тем, что LIKE-запросы по длинному тексту особенно дороги для традиционных подходов к индексированию, в то время как поиск по n-граммам позволяет быстро сузить пространство поиска до очень небольшого набора кандидатов.
На наборах данных, состоящих из записей, состоящих из одного слова, выигрыш меньше, но все равно существенный. В этом сценарии индекс n-грамм работает примерно на 80-100× быстрее, чем перебор, и на 45-55× быстрее, чем обычный инвертированный индекс. Хотя более короткий текст по своей природе дешевле для сканирования, подход, основанный на n-граммах, позволяет избежать ненужных сравнений и последовательно снижает стоимость запроса.
Заключение
Индекс Ngram ускоряет выполнение запросов LIKE, разбивая текст на n-граммы фиксированной длины и индексируя их с помощью инвертированной структуры. Такая конструкция превращает дорогостоящее сопоставление подстрок в эффективный поиск n-грамм с последующей минимальной проверкой. В результате удается избежать полнотекстового сканирования и сохранить точную семантику LIKE.
На практике этот подход эффективен в широком диапазоне рабочих нагрузок, особенно сильные результаты были получены при нечетком сопоставлении длинных текстовых полей. Поэтому индекс Ngram хорошо подходит для сценариев реального времени, таких как поиск кода, работа агентов службы поддержки, поиск юридических и медицинских документов, корпоративные базы знаний и академический поиск, где точное соответствие ключевым словам остается важным.
В то же время Ngram Index выигрывает от тщательной настройки. Выбор подходящих значений min_gram и max_gram имеет решающее значение для баланса между размером индекса и производительностью запросов. Если индекс Ngram настроен с учетом реальных шаблонов запросов, он представляет собой практичное, масштабируемое решение для высокопроизводительных запросов LIKE в производственных системах.
Для получения дополнительной информации об индексе Ngram ознакомьтесь с документацией ниже:
У вас есть вопросы или вы хотите получить подробную информацию о любой функции последней версии Milvus? Присоединяйтесь к нашему каналу Discord или создавайте проблемы на GitHub. Вы также можете забронировать 20-минутную индивидуальную сессию, чтобы получить понимание, руководство и ответы на свои вопросы через Milvus Office Hours.
Подробнее о возможностях Milvus 2.6
Представляем Milvus 2.6: доступный векторный поиск в миллиардных масштабах
Представляем функцию встраивания: Как Milvus 2.6 оптимизирует векторизацию и семантический поиск
Измельчение JSON в Milvus: 88,9-кратное ускорение фильтрации JSON с гибкостью
Представление AISAQ в Milvus: векторный поиск миллиардного масштаба стал на 3 200× дешевле по памяти
MinHash LSH в Milvus: секретное оружие для борьбы с дубликатами в обучающих данных LLM
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.
Get StartedLike the article? Spread the word



