Скалярный индекс
Milvus поддерживает фильтрованный поиск по скалярным и векторным полям. Чтобы повысить эффективность поиска по скалярным полям, в Milvus начиная с версии 2.1.0 была введена индексация по скалярным полям. В этой статье представлен обзор индексирования скалярных полей в Milvus, который поможет вам понять его значение и реализацию.
Обзор
При проведении поиска по векторному сходству в Milvus вы можете использовать логические операторы для организации скалярных полей в булевы выражения.
Когда Milvus получает поисковый запрос с таким булевым выражением, он разбирает булевое выражение на абстрактное синтаксическое дерево (AST), чтобы создать физический план для фильтрации атрибутов. Затем Milvus применяет физический план в каждом сегменте для создания набора битов в качестве результата фильтрации и включает результат в качестве параметра векторного поиска, чтобы сузить область поиска. В этом случае скорость векторного поиска в значительной степени зависит от скорости фильтрации атрибутов.
Фильтрация атрибутов в сегменте
Индексирование скалярных полей - это способ обеспечить скорость фильтрации атрибутов путем сортировки значений скалярных полей определенным образом для ускорения поиска информации.
Алгоритмы индексирования скалярных полей
Milvus стремится достичь низкого потребления памяти, высокой эффективности фильтрации и короткого времени загрузки с помощью алгоритмов индексации скалярных полей. Эти алгоритмы делятся на два основных типа: автоиндексация и инвертированная индексация.
Автоматическое индексирование
Milvus предоставляет опцию AUTOINDEX
, чтобы избавить вас от необходимости вручную выбирать тип индекса. При вызове метода create_index
, если не указан index_type
, Milvus автоматически выбирает наиболее подходящий тип индекса, основываясь на типе данных.
В следующей таблице перечислены типы данных, которые поддерживает Milvus, и соответствующие им алгоритмы автоматического индексирования.
Тип данных | Алгоритм автоматического индексирования |
---|---|
VARCHAR | Инвертированный индекс |
INT8 | Инвертированный индекс |
INT16 | Инвертированный индекс |
INT32 | Инвертированный индекс |
INT64 | Инвертированный индекс |
FLOAT | Инвертированный индекс |
DOUBLE | Инвертированный индекс |
Инвертированное индексирование
Инвертированное индексирование - это гибкий способ создания индекса для скалярного поля путем ручного указания параметров индекса. Этот метод хорошо подходит для различных сценариев, включая точечные запросы, запросы по совпадению шаблонов, полнотекстовый поиск, поиск в JSON, булевский поиск и даже запросы по совпадению префиксов.
Инвертированные индексы, реализованные в Milvus, работают на основе Tantivy, библиотеки полнотекстового поискового механизма. Tantivy гарантирует, что инвертированное индексирование в Milvus будет эффективным и быстрым.
Инвертированный индекс состоит из двух основных компонентов: словаря терминов и инвертированного списка. Словарь терминов включает все токенизированные слова, отсортированные по алфавиту, а инвертированный список содержит список документов, в которых встречается каждое слово. Такая схема позволяет выполнять точечные запросы и запросы по диапазону гораздо быстрее и эффективнее, чем поиск методом "грубой силы".
Диаграмма инвертированного индекса
Преимущества использования инвертированного индекса особенно очевидны при выполнении следующих операций:
- Точечный запрос: Например, при поиске документов, содержащих слово Milvus, процесс начинается с проверки наличия Milvus в словаре терминов. Если оно не найдено, то ни один документ не содержит этого слова. Если же оно найдено, то извлекается инвертированный список, связанный с Milvus, в котором указаны документы, содержащие это слово. Этот метод гораздо эффективнее, чем поиск "грубой силой" по миллиону документов, поскольку отсортированный словарь терминов значительно снижает временную сложность поиска слова Milvus.
- Запрос диапазона: Эффективность запросов по диапазону, таких как поиск документов, содержащих слова в алфавитном порядке больше, чем very, также повышается благодаря словарю отсортированных терминов. Этот подход более эффективен, чем поиск методом "грубой силы", обеспечивая более быстрые и точные результаты.
Результаты тестирования
Чтобы продемонстрировать улучшение производительности, обеспечиваемое скалярными индексами в Milvus, был проведен эксперимент по сравнению производительности нескольких выражений с использованием инвертированного индексирования и поиска методом "грубой силы" в необработанных данных.
Эксперимент включал в себя тестирование различных выражений в двух условиях: с инвертированным индексом и с перебором. Чтобы обеспечить справедливость, во всех тестах поддерживалось одинаковое распределение данных, каждый раз использовалась одна и та же коллекция. Перед каждым тестом коллекция освобождалась, индекс удалялся и перестраивался. Кроме того, перед каждым тестом выполнялся теплый запрос, чтобы минимизировать влияние холодных и горячих данных, и каждый запрос выполнялся несколько раз для обеспечения точности.
Для набора данных из 1 миллиона записей использование инвертированного индекса может обеспечить 30-кратное повышение производительности при выполнении точечных запросов. Для больших наборов данных прирост производительности может быть еще более значительным.
Рекомендации по производительности
Чтобы в полной мере использовать возможности Milvus по индексированию скалярных полей и раскрыть его мощь в поиске по векторному сходству, вам может понадобиться модель для оценки необходимого объема памяти на основе имеющихся у вас данных.
В следующих таблицах перечислены функции оценки для всех типов данных, которые поддерживает Milvus.
Числовые поля
Тип данных Функция оценки памяти (МБ) INT8 numOfRows * 12 / 1024 / 1024 INT16 numOfRows * 12 / 1024 / 1024 INT32 numOfRows * 12 / 1024 / 1024 INT64 numOfRows * 24 / 1024 / 1024 FLOAT32 numOfRows * 12 / 1024 / 1024 DOUBLE numOfRows * 24 / 1024 / 1024 Поля строк
Длина строки Функция оценки памяти (МБ) (0, 8] numOfRows * 128 / 1024 / 1024 (8, 16] numOfRows * 144 / 1024 / 1024 (16, 32] numOfRows * 160 / 1024 / 1024 (32, 64] numOfRows * 192 / 1024 / 1024 (64, 128] numOfRows * 256 / 1024 / 1024 (128, 65535] numOfRows * strLen * 1.5 / 1024 / 1024
Что дальше
Чтобы проиндексировать скалярное поле, прочитайте статью Построение индекса по скалярам.
Чтобы узнать больше о связанных терминах и правилах, упомянутых выше, читайте