Векторные индексы
Reindexer поддерживает три типа векторных индексов: brute-force, HNSW, IVF, и три типа метрик для вычисления расстояния между векторами: L2, inner_product, cosine.
Для всех типов векторных индексов следует явно указывать метрику metric и размерность dimension.
Вставлять в индекс и искать в нём можно только векторы указанной размерности. В индекс также можно вставить пустые векторы (пустой массив или null).
Параметры конфигурации для векторных индексов описаны в соответствующих разделах:
Создание индексов и добавление в уже существующий неймспейс описаны в разделах:
KNN и range search
KNN — это поиск k наиболее близких соседних векторов. Параметры, необходимые для KNN-запроса, зависят от конкретного типа индекса.
Range search — это поиск ближайших соседних векторов, расстояние до которых не превышает порогового значения, переданного с помощью параметра radius.
Название параметра
radiusпроисходит из его геометрического смысла дляL2-метрики: он ограничивает векторы выборки сферой заданного радиуса.
Для L2-метрики отсеиваются векторы, ранги которых больше значения параметра radius. Для метрик cosine и inner product — наоборот. Также для метрик cosine и inner product значения radius могут буть отрицательными. Задание неположительного радиуса для L2-метрики не ошибочно, но бессмысленно: результат запроса заведомо будет пустым.
Во избежание путаницы при использовании
L2-метрики следует учитывать, что в целях производительности из рангов векторов не извлекаются квадратные корни, так как это не влияет на порядок выдачи. Поэтому ранги представляют собой квадраты расстояний до вектора запроса. И, хотя параметр и называетсяradius, переданное значение при поиске интерпретируется как квадрат расстояния до вектора запроса.
Таким образом, общими параметрами для всех типов индексов KNN являются:
k— максимальное количество документов, возвращаемых из индекса для последующей фильтрации,radius— фильтр по рангам векторов.
Обязательно должен быть задан хотя бы один из этих параметров. При задании обоих параметров фильтрация будет выполнена так, чтобы удовлетворять обоим условиям.
Так как range search работает на той же алгоритмической базе, что и KNN, далее под KNN-поиском подразумевается любой из них, в том числе их комбинация.
Списки используемых при поиске параметров и их назначение приведены на страницах соотвествующих индексов:
- параметры выборки из индекса brute-force,
- параметры выборки из индекса HNSW,
- параметры выборки из индекса IVF.
Особенности реализации KNN-запросов:
-
KNN-фильтр можно использовать в запросах с дополнительной фильтрацией, если условия фильтрации соединены с KNN-фильтром через оператор
AND:SELECT * FROM test_ns WHERE KNN(vec_ivf, [2.4, 3.5, ...], k=100, radius=21.12) AND value > 10 AND ( id < 7 OR is_active = true ) INNER JOIN ( SELECT * FROM second_ns ) ON test_ns.id = second_ns.id LEFT JOIN ( SELECT * FROM third_ns ) ON test_ns.id = third_ns.id -
На текущий момент нет возможности использовать несколько KNN-фильтров в запросе.
-
На текущий момент нет возможности использовать KNN-выборку внутри joined-подзапроса.
Базовые примеры KNN-запросов для конкретных индексов описаны в следующих разделах:
- Примеры KNN-запросов к brute-force-индексу,
- Примеры KNN-запросов к HNSW-индексу,
- Примеры KNN-запросов к IVF-индексу.
Выдача векторных полей
По умолчанию векторные поля исключаются из результатов всех запросов к неймспейсам, содержащим векторные индексы.
Если необходимо получить векторные поля, следует указать это явно в запросе, либо перечислив нужные поля, либо запросив выдачу всех векторных полей, используя vectors().
Без явного запроса векторных полей:
SELECT * FROM test_ns;
db.Query("test_ns")
db.Query("test_ns").Select("*")
curl --location --request POST 'http://127.0.0.1:9088/api/v1/db/vectors_db/query' \
--header 'Content-Type: application/json' \
--data-raw '{
"namespace": "test_ns",
"type": "select",
"select_filter": ["*"]
}'
Результат в JSON-формате:
{"id": 0}
С запросом конкретных полей:
SELECT *, vec_bf FROM test_ns;
db.Query("test_ns").Select("*", "vec_bf")
curl --location --request POST 'http://127.0.0.1:9088/api/v1/db/vectors_db/query' \
--header 'Content-Type: application/json' \
--data-raw '{
"namespace": "test_ns",
"type": "select",
"select_filter": ["*", "vec_bf"]
}'
Результат в JSON-формате:
{"id": 0, "vec_bf": [0.0, 1.1, ...]}
С запросом всех векторных полей:
SELECT *, vectors() FROM test_ns;
db.Query("test_ns").Select("*", "vectors()")
db.Query("test_ns").SelectAllFields()
curl --location --request POST 'http://127.0.0.1:9088/api/v1/db/vectors_db/query' \
--header 'Content-Type: application/json' \
--data-raw '{
"namespace": "test_ns",
"type": "select",
"select_filter": ["*", "vectors()"]
}'
Результат в JSON-формате:
{"id": 0, "vec_bf": [0.0, 1.1, ...], "vec_hnsw": [1.2, 3.5, ...], "vec_ivf": [5.1, 4.7, ...]}
Получение ранга/расстояния
По умолчанию результаты запросов с KNN сортируются по rank (для векторного поиска он соответствует расстоянию между векторами).
Для индексов с метрикой L2 — от меньшего значения к большему, а с метриками inner_product и cosine — от большего значения к меньшему.
Что согласуется с наилучшим соответствием для указанных метрик.
Когда есть необходимость узнать rank каждого документа в результате запроса, его нужно запросить явно через функцию RANK() в SQL или WithRank() в GO:
- примеры
rank-запросов для brute-force, - примеры
rank-запросов для HNSW, - примеры
rank-запросов для IVF.
Также rank можно использовать в сортировке по выражению. Подробно описано в разделе сортировка и ограничение выдачи.
Дополнительные action-команды
Эти команды могут быть использованы при помощи их вставки через upsert в #config-неймспейс.
Удаление дискового кеша для ANN-индексов
Формат команды в JSON:
{
"type": "action",
"action": {
"command": "drop_ann_storage_cache",
"namespace": "*",
"index": "*"
}
}
Пример использования через reindexer_tool:
reindexer_tool \
--dsn cproto://127.0.0.1:6534/vectors_db \
-c '\upsert #config {"type":"action","action":{"command":"drop_ann_storage_cache", "namespace":"*", "index":"*"}}'
Команда может быть полезна для случаев, когда требуется форсировать пересоздание дискового кеша для ANN-индексов, либо полностью его отключить (используя совместно с переменной среды RX_DISABLE_ANN_CACHE).
namespace- определяет целевой неймспейс (*- применяет команду ко всем неймспейсам);index- определяет целевой индекс (*- применяет команду ко всем подходящим индексам в неймспейсе).
Переменные среды, влияющие на работу векторных индексов
| Имя переменной | Описание |
|---|---|
| RX_DISABLE_ANN_CACHE | Если эта переменная установлена, то reindexer отключает использование дискового ANN-кеша для построения векторных индексов при загрузке данных с диска во время запуска (в общем случае отключать кеш не рекомендуется, так как это сильно снижает скорость запуска). |
| RX_TARGET_INSTRUCTIONS | Ожидает одно из значений: avx512, avx2, avx или sse. Позволяет выбрать набор векторных инструкций, используемых для функций вычисления расстояния. По умолчанию, если переменная не задана, reindexer использует «лучшие» из доступных для CPU, на котором запущен, но в некоторых случаях avx512 может оказываться менее эффективен, чем avx2/avx в многопоточном окружении. |