---
metadata:
  - name: generator
    content: Diplodoc Platform v5.50.4
alternate:
  - https://ydb.tech/docs/en/dev/vector-indexes.md?version=v25.4
  - https://ydb.tech/docs/ru/dev/vector-indexes.md?version=v25.4
sourcePath: ru/core/dev/vector-indexes.md
---
> **Documentation Index:** Fetch the complete configuration index at https://ydb.tech/docs/ru/llms.txt

# Векторные индексы

[Векторные индексы](https://ydb.tech/docs/ru/concepts/glossary.md?version=v25.4#vector-index) — это специализированные структуры данных, которые позволяют эффективно выполнять [векторный поиск](https://ydb.tech/docs/ru/concepts/query_execution/vector_search.md?version=v25.4) в многомерных пространствах. В отличие от [вторичных индексов](https://ydb.tech/docs/ru/concepts/glossary.md?version=v25.4#secondary-index), которые оптимизируют поиск по равенству или диапазону, векторные индексы позволяют выполнять приближенный поиск на основе [функций схожести или расстояния](https://ydb.tech/docs/ru/yql/reference/udf/list/knn.md?version=v25.4#functions).

Данные в таблице YDB хранятся и сортируются по первичному ключу, что обеспечивает эффективный поиск по точному совпадению и сканирование диапазонов. Векторные индексы предоставляют аналогичную эффективность для поиска ближайших соседей в векторных пространствах.

## Характеристики векторных индексов {#characteristics}

Векторные индексы в YDB решают задачу поиска ближайших соседей с использованием [функций схожести или расстояния](https://ydb.tech/docs/ru/yql/reference/udf/list/knn.md?version=v25.4#functions). Поддерживается несколько функций расстояния/схожести: "inner_product", "cosine" (схожесть) и "cosine", "euclidean", "manhattan" (расстояние).

В текущей реализации доступен один тип индекса: `vector_kmeans_tree`.

## Векторный индекс типа `vector_kmeans_tree` {#kmeans-tree-type}

Индекс `vector_kmeans_tree` реализует иерархическую кластеризацию данных. Структура индекса включает:

1. Иерархическая кластеризация:

    * индекс строит несколько уровней k-means кластеров;
    * на каждом уровне векторы распределяются по заданному количеству кластеров в степени уровня;
    * первый уровень кластеризует весь набор данных;
    * последующие уровни рекурсивно кластеризуют содержимое каждого родительского кластера.

2. Процесс поиска:

    * поиск идет рекурсивно от первого уровня к последующим;
    * при выполнении запросов индекс анализирует только наиболее перспективные кластеры;
    * такое усечение пространства поиска позволяет избежать полного перебора всех векторов.

3. Параметры:

    * `levels`: число уровней в дереве, задает глубину поиска (рекомендуется 1-3);
    * `clusters`: количество кластеров в k-means, определяющее ширину поиска (рекомендуется 64-512).

Внутри векторный индекс состоит из скрытых индексных таблиц вида `indexImpl*Table`. В [запросах на выборку](https://ydb.tech/docs/ru/yql/reference/syntax/select/vector_index.md?version=v25.4) с использованием векторного индекса эти таблицы отображаются в [статистике запросов](https://ydb.tech/docs/ru/dev/query-execution-optimization/query-plans-optimization.md?version=v25.4). Подробнее об устройстве векторного индекса см. в отдельной статье [Векторный индекс вида vector_kmeans_tree](https://ydb.tech/docs/ru/dev/vector-indexes-kmeans-tree-type.md?version=v25.4).

## Виды векторных индексов {#types}

Векторный индекс может быть **покрывающим**, что означает включение дополнительных колонок для возможности чтения из индекса без обращения к основной таблице.

Или же он может быть с поддержкой **фильтрации**, что позволяет учитывать дополнительные колонки для быстрой фильтрации при выполнении чтения.

Ниже приведены примеры создания векторного индекса различных типов.


### Базовый векторный индекс {#basic}

Глобальный векторный индекс по колонке `embedding`:  

```yql
ALTER TABLE my_table
  ADD INDEX my_index
  GLOBAL USING vector_kmeans_tree
  ON (embedding)
  WITH (distance=cosine, vector_type="uint8", vector_dimension=512, levels=2, clusters=128);
```

### Векторный индекс с покрывающими колонками {#covering}

Покрывающий векторный индекс, включающий дополнительную колонку `data`, чтобы избежать чтения из основной таблицы при поиске:  

```yql
ALTER TABLE my_table
  ADD INDEX my_index
  GLOBAL USING vector_kmeans_tree
  ON (embedding) COVER (data)
  WITH (distance=cosine, vector_type="uint8", vector_dimension=512, levels=2, clusters=128);
```

### Векторный индекс с фильтрацией {#filtered}

Векторный индекс с фильтрацией, позволяющий фильтровать по колонке `user` в момент выполнения векторного поиска:

```yql
ALTER TABLE my_table
  ADD INDEX my_index
  GLOBAL USING vector_kmeans_tree
  ON (user, embedding)
  WITH (distance=cosine, vector_type="uint8", vector_dimension=512, levels=2, clusters=128);
```

### Векторный индекс с фильтрацией и покрывающими колонками {#filtered-covering}

Векторный индекс с фильтрацией и покрывающими колонками:  

```yql
ALTER TABLE my_table
  ADD INDEX my_index
  GLOBAL USING vector_kmeans_tree
  ON (user, embedding) COVER (data)
  WITH (distance=cosine, vector_type="uint8", vector_dimension=512, levels=2, clusters=128);
```

### Перекрытие кластеров {#overlap-clusters}

Векторный индекс в YDB может добавлять каждый вектор в несколько кластеров с целью
улучшения полноты и скорости поиска:

```yql
ALTER TABLE my_table
  ADD INDEX my_index
  GLOBAL USING vector_kmeans_tree
  ON (embedding)
  WITH (distance=cosine, vector_type="uint8", vector_dimension=512, levels=2, clusters=128, overlap_clusters=3);
```

В данном примере каждый вектор будет добавлен в 3 ближайших кластера вместо 1.

Использование такого индекса позволяет значительно улучшить полноту поиска даже с небольшими значениями PRAGMA
[KMeansTreeSearchTopSize](https://ydb.tech/docs/ru/yql/reference/syntax/select/vector_index.md?version=v25.4#kmeanstreesearchtopsize) (например, 3).

## Создание векторных индексов {#creation}

Векторные индексы можно создавать:

* при создании таблицы с помощью YQL-оператора [CREATE TABLE](https://ydb.tech/docs/ru/yql/reference/syntax/create_table/vector_index.md?version=v25.4);
* добавлять к существующей таблице с помощью YQL-оператора [ALTER TABLE](https://ydb.tech/docs/ru/yql/reference/syntax/alter_table/indexes.md?version=v25.4).

## Использование векторных индексов {#select}

Запросы к векторным индексам выполняются с использованием синтаксиса `VIEW` в YQL:

```yql
DECLARE $query_vector AS List<Uint8>;

SELECT user, data
FROM my_table VIEW my_index
ORDER BY Knn::CosineSimilarity(embedding, $query_vector) DESC
LIMIT 10;
```

Для индексов с фильтрацией укажите соответствующие колонки в условии `WHERE`:

```yql
DECLARE $query_vector AS List<Uint8>;

SELECT user, data
FROM my_table VIEW my_index
WHERE user = 'john'
ORDER BY Knn::CosineSimilarity(embedding, $query_vector) DESC
LIMIT 10;
```

Подробнее о выполнении запросов `SELECT` с использованием векторных индексов можно прочитать в разделе [VIEW VECTOR INDEX](https://ydb.tech/docs/ru/yql/reference/syntax/select/vector_index.md?version=v25.4).

{% note info %}

Если не использовать выражение `VIEW`, запрос выполнит полное сканирование таблицы с попарным сравнением векторов.

Рекомендуется проверять оптимальность написанного запроса, используя [статистику запросов](https://ydb.tech/docs/ru/dev/query-execution-optimization/query-plans-optimization.md?version=v25.4). В частности, следует следить за отсутствием полного сканирования (full scan) основной таблицы.

{% endnote %}

## Обновление векторных индексов {#update}

При обновлении таблицы с векторным индексом его внутренняя структура — дерево кластеров (групп схожих векторов) — не перестраивается. Новые или изменённые записи лишь распределяются по уже существующим кластерам.

Со временем это может приводить к деградации индекса, которая проявляется двумя способами:

- Снижение полноты — индекс может возвращать меньше релевантных результатов, так как кластеры перестают отражать истинную структуру данных;
- Снижение производительности — если кластеры становятся несбалансированными (например, один кластер содержит слишком много записей), поиск замедляется.

Степень деградации зависит от характера обновлений:

- Если индекс был построен на репрезентативной выборке (например, случайные 50 % данных), а затем добавлены оставшиеся записи, структура остаётся актуальной, и деградация минимальна;
- Если же изначально отсутствовали целые группы схожих векторов, кластеры могут разделять пространство некорректно, и качество поиска может существенно упасть.

Крайним случаем является индекс, созданный на пустой таблице: в этом случае он содержит только один кластер, и все новые записи попадают в него. Поиск по такому индексу эквивалентен полному сканированию всей таблицы.

Чтобы избежать деградации:

- Не создавайте векторный индекс на пустой таблице;
- Если в таблице накопилось много новых данных, [постройте новый индекс](https://ydb.tech/docs/ru/yql/reference/syntax/alter_table/indexes.md?version=v25.4) и [атомарно замените](https://ydb.tech/docs/ru/reference/ydb-cli/commands/secondary_index.md?version=v25.4#rename) старый индекс на вновь построенный.

## Рецепты работы с векторным индексом {#vector-index-recipes}

Для начала работы с векторным индексом можно воспользоваться следующими рецептами:

* [YDB CLI & YQL](../recipes/vector-search)
* [YDB SDK: Python, C++](https://ydb.tech/docs/ru/recipes/ydb-sdk/vector-search.md?version=v25.4)
