Vector нагрузка
Позволяет тестировать производительность и полноту векторного поиска YDB с помощью точного и приближённого поиска. Поддерживается тестирование обычных векторных индексов и векторных индексов с фильтрацией.
Нагрузка позволяет загружать векторы из реального датасета (например, Wikipedia embeddings) или генерировать случайные синтетические векторы. После загрузки данных можно построить векторный индекс, запустить поисковые запросы для измерения полноты и производительности и очистить таблицы нагрузки.
Структура команды
ydb [global options...] workload vector [options...] <subcommand>
Подкоманды:
vector YDB vector workload.
├─ init Инициализация таблиц для нагрузки
├─ import Загрузка данных в таблицы нагрузки
│ ├─ files Импорт векторов из файлов
│ └─ generator Генерация случайных векторов
├─ build-index Создание и инициализация векторного индекса
├─ drop-index Удаление векторного индекса
├─ run Запуск нагрузки
│ ├─ select Поиск векторов и измерение производительности/полноты
│ └─ upsert Вставка или обновление строк с векторами
└─ clean Удаление таблиц, созданных для нагрузочного тестирования
Инициализация нагрузки
Создайте таблицу для нагрузочного тестирования:
ydb workload vector init
Доступные параметры
| Имя | Описание | Значение по умолчанию |
|---|---|---|
--table <имя> |
Имя основной таблицы для хранения векторов. | vector_index_workload |
--min-partitions <значение> |
Минимальное количество партиций таблицы. | 40 |
--partition-size <значение> |
Целевой размер партиции, в МБ. | 2000 |
--auto-partition <значение> |
Включить автопартицирование по нагрузке (1 — включено, 0 — выключено). |
1 |
--prefixed |
Добавить столбец prefix в таблицу для использования с фильтрующим (prefixed) векторным индексом. |
|
--clear |
Удалить и пересоздать таблицу, если она уже существует. | |
--dry-run |
Только вывести DDL-запрос, не выполняя его. |
Создаваемая таблица имеет следующую схему:
id Uint64 NOT NULL— первичный ключ;embedding String— сериализованный вектор-эмбеддинг;prefix Uint64 NOT NULL(только при указании--prefixed) — столбец фильтра для prefixed-индексов.
Загрузка данных
После инициализации загрузите данные в таблицу. Доступны две подкоманды: files — для импорта векторов из готового датасета, и generator — для генерации синтетических случайных векторов.
После завершения импорта автоматически строится векторный индекс с именем index по столбцу embedding (если не указано --index-type None).
Импорт из файлов
Импорт векторов из файлов (CSV, TSV или Parquet, возможно в сжатом формате gzip). Датасет должен содержать столбцы id и embedding. Дополнительные столбцы игнорируются.
В файлах CSV/TSV эмбеддинги должны быть представлены в виде списка чисел с плавающей точкой, например "[ 1.0, 2.0, 3.0 ]". В файлах Parquet эмбеддинги могут быть как списком float32, так и уже сериализованными бинарными эмбеддингами YDB.
Пример запуска:
ydb workload vector import files
Доступные параметры
| Имя | Описание | Значение по умолчанию |
|---|---|---|
--input <путь> или -i <путь> |
Путь к файлу или директории с датасетом. Поддерживаемые форматы: CSV/TSV (с опциональным gzip-сжатием), Parquet. Импортируются только столбцы id и embedding. |
Обязательный |
--format <формат> |
Формат файлов. Один из csv, tsv, parquet. Если указан, из директории импортируются только файлы соответствующего формата. Если не указан — формат определяется по расширению файла. |
|
--embedding-column-name <имя> |
Альтернативное имя исходного столбца с эмбеддингами. | embedding |
--table <имя> |
Имя таблицы для загрузки данных. | vector_index_workload |
--index <имя> |
Имя векторного индекса, который будет построен после импорта. | index |
--index-type <тип> |
Тип индекса, строимого после импорта. Возможные значения: None, KmeansTree. Указание None отключает построение индекса. |
KmeansTree |
--vector-type <тип> |
Тип векторов. Один из float, int8, uint8, bit. |
float |
--vector-dimension <значение> |
Размерность векторов. | 1024 |
--distance <значение> |
Функция расстояния или сходства. Один из inner_product, cosine, euclidean, manhattan. |
inner_product |
--kmeans-tree-levels <значение> |
Количество уровней в дереве k-means. Если не задано, определяется сервером автоматически. См. тип kmeans-tree. | Автоопределение |
--kmeans-tree-clusters <значение> |
Количество кластеров k-means. Если не задано, определяется сервером автоматически. См. тип kmeans-tree. | Автоопределение |
--kmeans-tree-covering <значение> |
Создавать покрывающий индекс (1 — да, 0 — нет). |
0 |
--kmeans-tree-prefixed <значение> |
Создавать prefixed (фильтрующий) индекс (1 — да, 0 — нет). Таблица должна быть создана с параметром --prefixed. |
0 |
Примечание
Подробнее о параметрах построения индекса --kmeans-tree-* смотрите в разделе Тип kmeans-tree.
Общие параметры команды import
| Имя | Описание | Значение по умолчанию |
|---|---|---|
--upload-threads <значение> или -t <значение> |
Количество потоков исполнения для подготовки данных. | Рассчитывается автоматически и равно числу доступных ядер на клиентской машине. |
--bulk-size <значение> |
Размер порции для отправки данных в строках. | 10000 |
--max-in-flight <значение> |
Максимальное количество порций данных, одновременно находящихся в обработке. | 128 |
--file-output-path <значение> или -f <путь> |
Если эта опция установлена, данные не будут загружены в базу данных, а будут сохранены в каталоге <путь>. |
Генерация синтетических данных
Генерация случайных векторов и загрузка их в таблицу. Компоненты векторов выбираются из равномерного распределения и сериализуются в бинарный формат эмбеддингов YDB.
ydb workload vector import generator
Доступные параметры
| Имя | Описание | Значение по умолчанию |
|---|---|---|
--rows <значение> |
Количество строк для генерации. | 10000 |
--prefix-count <значение> |
Количество различных значений префикса для prefixed-индекса. | 100 |
--seed <значение> |
Зерно для генератора случайных чисел. | 42 |
--table <имя> |
Имя таблицы для загрузки данных. | vector_index_workload |
--index <имя> |
Имя векторного индекса, который будет построен после импорта. | index |
--index-type <тип> |
Тип индекса. Возможные значения: None, KmeansTree. |
KmeansTree |
--vector-type <тип> |
Тип векторов. Один из float, int8, uint8, bit. |
float |
--vector-dimension <значение> |
Размерность векторов. | 1024 |
--distance <значение> |
Функция расстояния или сходства. | inner_product |
--kmeans-tree-levels <значение> |
Количество уровней в дереве k-means. Если не задано, определяется сервером автоматически. | Автоопределение |
--kmeans-tree-clusters <значение> |
Количество кластеров k-means. Если не задано, определяется сервером автоматически. | Автоопределение |
--kmeans-tree-covering <значение> |
Создавать покрывающий индекс. | 0 |
--kmeans-tree-prefixed <значение> |
Создавать prefixed-индекс. | 0 |
Примечание
Подробнее о параметрах построения индекса --kmeans-tree-* смотрите в разделе Тип kmeans-tree.
Общие параметры команды import
| Имя | Описание | Значение по умолчанию |
|---|---|---|
--upload-threads <значение> или -t <значение> |
Количество потоков исполнения для подготовки данных. | Рассчитывается автоматически и равно числу доступных ядер на клиентской машине. |
--bulk-size <значение> |
Размер порции для отправки данных в строках. | 10000 |
--max-in-flight <значение> |
Максимальное количество порций данных, одновременно находящихся в обработке. | 128 |
--file-output-path <значение> или -f <путь> |
Если эта опция установлена, данные не будут загружены в базу данных, а будут сохранены в каталоге <путь>. |
Построение векторного индекса
Если данные загружались с параметром --index-type None, или если нужно построить дополнительный индекс с другими параметрами, векторный индекс можно построить на существующей таблице командой build-index.
ydb workload vector build-index --distance cosine
Доступные параметры
| Имя | Описание | Значение по умолчанию |
|---|---|---|
--table <имя> |
Имя таблицы, на которой строится индекс. | vector_index_workload |
--index <имя> |
Имя создаваемого индекса. | index |
--vector-type <тип> |
Тип векторов. Один из float, int8, uint8, bit. |
float |
--vector-dimension <значение> |
Размерность векторов. | 1024 |
--distance <значение> |
Функция расстояния или сходства. | inner_product |
--kmeans-tree-levels <значение> |
Количество уровней в дереве k-means. Если не задано, определяется сервером автоматически. | Автоопределение |
--kmeans-tree-clusters <значение> |
Количество кластеров k-means. Если не задано, определяется сервером автоматически. | Автоопределение |
--dry-run |
Только вывести DDL-запрос, не выполняя его. |
Примечание
Подробнее о параметрах построения индекса --kmeans-tree-* смотрите в разделе Тип kmeans-tree.
Удаление векторного индекса
Удаление ранее созданного векторного индекса.
ydb workload vector drop-index
Доступные параметры
| Имя | Описание | Значение по умолчанию |
|---|---|---|
--table <имя> |
Имя таблицы, в которой находится индекс. | vector_index_workload |
--index <имя> |
Имя удаляемого индекса. | index |
--dry-run |
Только вывести DDL-запрос, не выполняя его. |
Запуск нагрузки
Запустите нагрузочное тестирование в одном из двух режимов: select (векторный поиск) или upsert (вставка новых векторов).
Нагрузочное тестирование поисковых запросов
Выполняет запросы векторного поиска к индексированной таблице. Опционально измеряет полноту, сравнивая результаты приближённого поиска с точным (полным перебором), затем выполняет замер производительности.
ydb workload vector run select --recall
Доступные параметры
| Имя | Описание | Значение по умолчанию |
|---|---|---|
--table <имя> |
Имя основной таблицы с векторами. | vector_index_workload |
--index <имя> |
Имя векторного индекса. | index |
--query-table <имя> |
Имя таблицы с тестовой выборкой векторов. Если не задано, используются случайные строки из основной таблицы. | |
--targets <значение> |
Размер тестовой выборки. | 100 |
--limit <значение> |
Максимальное число записей в результатах одного запроса. | 5 |
--kmeans-tree-clusters <значение> |
Максимальное число кластеров, проверяемых во время поиска (KMeansTreeSearchTopSize). | 1 |
--recall |
Включить замер полноты приближённого поиска относительно точного. | |
--recall-threads <значение> |
Число параллельных запросов при оценке полноты. | 10 |
--non-indexed |
Использовать настройки поиска из индекса, но искать без индекса, полным перебором. | |
--stale-ro |
Чтение в режиме StaleRO. |
Важно
Обратите внимание на параметр --kmeans-tree-clusters — его увеличение значительно повышает полноту поиска ценой его замедления. Попробуйте значения в пределах от 1 до числа кластеров, указанного при создании индекса.
Общие параметры для всех видов нагрузки
| Имя | Описание | Значение по умолчанию |
|---|---|---|
--dry-run |
Не выполнять инициализационные запросы, а только вывести их текст. | |
--check-canonical или -c |
Использовать специальную версию запросов (они имеют детерминированные ответы) и сверять результаты с каноническими. | |
--output <значение> |
Имя файла, в котором будут сохранены результаты выполнения запросов. | results.out |
--iterations <значение> |
Количество выполнений каждого из запросов нагрузки. | 1 |
--json <имя> |
Имя файла, в котором будет сохранена статистика выполнения запросов в формате json. |
Файл не сохраняется |
--ministat <имя> |
Имя файла, в котором будет сохранена статистика выполнения запросов в формате ministat. |
Файл не сохраняется |
--csv <имя> |
Имя файла для сохранения CSV-версии таблицы с результатами. | Файл не сохраняется |
--plan <имя> |
Имя файла для сохранения плана запроса. Если задано, то сохраняются файлы <имя>.<номер запроса>.explain и <имя>.<номер запроса>.<номер итерации> с планами в нескольких форматах: ast, json, svg и table. |
Планы не сохраняются. |
--query-prefix <префикс> |
Префикс запроса. Каждый префикс будет добавлен отдельной строкой в начало каждого запроса. Если нужно указать несколько префиксов, используйте параметр несколько раз. | По умолчанию не задан |
--retries |
Количество повторных попыток выполнения каждого запроса | 0 |
--include |
Имена, номера или диапазоны номеров запросов, которые нужно выполнить в рамках нагрузки. Указываются через запятую, например: 1,2,4-6. |
Все запросы |
--exclude |
Имена, номера или диапазоны номеров запросов, которые нужно исключить из нагрузки. Указываются через запятую, например: 1,2,4-6. |
|
--verbose или -v |
Выводить больше информации на экран в процессе выполнения запросов. | |
--global-timeout <значение> |
Общий таймаут на выполнение всех запросов. Задаётся в текстовом формате, например: 0.5s, 1m, 100us и т.д. |
Отсутствует. Время не ограничено. |
--request-timeout <значение> |
Таймаут на выполнение каждой итерации каждого запроса. Задаётся в текстовом формате, например: 0.5s, 1m, 100us и т.д. |
Отсутствует. Время не ограничено. |
--threads <значение> или -t <значение> |
Количество потоков, генерирующих нагрузку. Ноль означает, что запросы будут выполняться в основном потоке; при ином значении запросы будут перемешаны. | 0 |
--stats <значение> |
Режим сбора расширенной статистики выполнения. Возможные значения: full, profile. |
full |
Нагрузочное тестирование на запись
Непрерывно вставляет новые строки с векторами в таблицу, генерируя случайные эмбеддинги «на лету».
ydb workload vector run upsert
Доступные параметры
| Имя | Описание | Значение по умолчанию |
|---|---|---|
--table <имя> |
Имя таблицы для вставки. | vector_index_workload |
--index <имя> |
Имя векторного индекса. | index |
--bulk-size <значение> |
Количество строк в одном пакете upsert. | 100 |
--prefixed |
Генерировать вставки со столбцом prefix (для prefixed-индексов). |
|
--prefix-count <значение> |
Количество различных значений префикса. Используется только при указании --prefixed. |
1000 |
Общие параметры для всех видов нагрузки
| Имя | Описание | Значение по умолчанию |
|---|---|---|
--dry-run |
Не выполнять инициализационные запросы, а только вывести их текст. | |
--check-canonical или -c |
Использовать специальную версию запросов (они имеют детерминированные ответы) и сверять результаты с каноническими. | |
--output <значение> |
Имя файла, в котором будут сохранены результаты выполнения запросов. | results.out |
--iterations <значение> |
Количество выполнений каждого из запросов нагрузки. | 1 |
--json <имя> |
Имя файла, в котором будет сохранена статистика выполнения запросов в формате json. |
Файл не сохраняется |
--ministat <имя> |
Имя файла, в котором будет сохранена статистика выполнения запросов в формате ministat. |
Файл не сохраняется |
--csv <имя> |
Имя файла для сохранения CSV-версии таблицы с результатами. | Файл не сохраняется |
--plan <имя> |
Имя файла для сохранения плана запроса. Если задано, то сохраняются файлы <имя>.<номер запроса>.explain и <имя>.<номер запроса>.<номер итерации> с планами в нескольких форматах: ast, json, svg и table. |
Планы не сохраняются. |
--query-prefix <префикс> |
Префикс запроса. Каждый префикс будет добавлен отдельной строкой в начало каждого запроса. Если нужно указать несколько префиксов, используйте параметр несколько раз. | По умолчанию не задан |
--retries |
Количество повторных попыток выполнения каждого запроса | 0 |
--include |
Имена, номера или диапазоны номеров запросов, которые нужно выполнить в рамках нагрузки. Указываются через запятую, например: 1,2,4-6. |
Все запросы |
--exclude |
Имена, номера или диапазоны номеров запросов, которые нужно исключить из нагрузки. Указываются через запятую, например: 1,2,4-6. |
|
--verbose или -v |
Выводить больше информации на экран в процессе выполнения запросов. | |
--global-timeout <значение> |
Общий таймаут на выполнение всех запросов. Задаётся в текстовом формате, например: 0.5s, 1m, 100us и т.д. |
Отсутствует. Время не ограничено. |
--request-timeout <значение> |
Таймаут на выполнение каждой итерации каждого запроса. Задаётся в текстовом формате, например: 0.5s, 1m, 100us и т.д. |
Отсутствует. Время не ограничено. |
--threads <значение> или -t <значение> |
Количество потоков, генерирующих нагрузку. Ноль означает, что запросы будут выполняться в основном потоке; при ином значении запросы будут перемешаны. | 0 |
--stats <значение> |
Режим сбора расширенной статистики выполнения. Возможные значения: full, profile. |
full |
Очистка данных
Удаление таблиц, созданных для нагрузочного тестирования:
ydb workload vector clean
Алгоритм тестирования
Режим run select выполняет следующие шаги:
- Формируется тестовая выборка:
- Если задана таблица с тестовой выборкой (
--query-table), из неё выбираются первые--targetsзаписей по порядку первичного ключа. - В противном случае выбираются случайные
--targetsзаписей из основной таблицы.
- Если задана таблица с тестовой выборкой (
- Производится оценка полноты (если указан
--recall):- Для каждого элемента тестовой выборки запускается по два запроса.
- Первый запрос — точный векторный поиск (полный перебор) по близости к векторной колонке, формируя эталонное множество результатов
R_exact. - Второй запрос — приближённый векторный поиск на основе векторного индекса, получая множество результатов
R_approx. - Если выбран индекс с фильтрацией, то оба поиска проводятся только среди записей с соответствующими значениями колонок фильтров.
- Вычисляется полнота приближённого поиска по формуле (здесь
|A|— число элементов в множестве A, аA ∩ B— пересечение множеств A и B).
- Производится оценка скорости:
- В течение заданного времени и в заданное число параллельных потоков запускаются запросы поиска по индексу.
- Каждый запрос запускается для случайного элемента тестовой выборки.
- Вычисляется средняя производительность (RPS) и время ответа на разных квантилях.
Примеры использования
Пример с генерируемыми данными
-
Инициализируйте таблицу для нагрузочного тестирования:
ydb workload vector init -
Сгенерируйте и загрузите синтетические векторы:
ydb workload vector import generator --rows 100000 --distance cosine -
Запустите нагрузку на поиск:
ydb workload vector run select --recallПример вывода:
Recall: 0.8950 Window Txs Txs/Sec Retries Errors p50(ms) p95(ms) p99(ms) pMax(ms) 1 100 100 0 0 5 8 12 15 2 98 98 0 0 5 9 13 16 ... Total Txs Txs/Sec Retries Errors p50(ms) p95(ms) p99(ms) pMax(ms) 10 980 98.0 0 0 5 9 14 18Описание колонок:
Window— Порядковый номер временного окна (например, каждая секунда или фиксированный интервал).Txs— Количество успешно выполненных транзакций в данном окне (или общее количество по всем окнам в итоговой строке).Txs/Sec— Количество транзакций в секунду для данного окна (или среднее значение для итоговой строки).Retries— Количество автоматических повторных попыток из-за временных ошибок (например, конфликтов или троттлинга).Errors— Количество неисправимых ошибок.p50(ms)— Медианная (50-й перцентиль) задержка выполнения транзакции в миллисекундах.p95(ms)— Задержка на уровне 95-го перцентиля (миллисекунды).p99(ms)— Задержка на уровне 99-го перцентиля (миллисекунды).pMax(ms)— Максимальная наблюдаемая задержка в пределах окна (или глобальный максимум для итоговой строки).
-
Запустите нагрузку на запись:
ydb workload vector run upsert -
Удаление таблиц, созданных для нагрузочного тестирования:
ydb workload vector clean
Пример с внешним датасетом
-
Подготовьте таблицы и загрузите данные. Пример создания таблицы и загрузки данных приведён в рецепте Векторный индекс с загрузкой внешнего набора данных.
Примеры создания векторных индексов доступны на странице документации Векторные индексы.
-
Запустите нагрузку на поиск:
ydb -e grpc://hostname:2135 -d /Root/testdb workload vector run select \ --table wikipedia --index idx_vector \ --query-table wikipedia_sample --recallПример вывода:
Recall: 0.8950 Window Txs Txs/Sec Retries Errors p50(ms) p95(ms) p99(ms) pMax(ms) 1 100 100 0 0 5 8 12 15 2 98 98 0 0 5 9 13 16 ... Total Txs Txs/Sec Retries Errors p50(ms) p95(ms) p99(ms) pMax(ms) 10 980 98.0 0 0 5 9 14 18
Примечания
- Поисковая нагрузка генерирует SQL-запросы выборки ближайших строк по векторному расстоянию из таблицы
--tableпо индексу--index. - Указывать названия колонок (векторной, фильтра, первичного ключа) и функцию расстояния не нужно — они извлекаются автоматически из определения индекса.
- Случайный выбор тестовых векторов из таблицы
--tableработает только в том случае, если первичный ключ таблицы — целочисленный. - Если используется
--query-table, в обеих таблицах имена векторной колонки и колонки фильтра должны совпадать. - Оценка полноты поиска (
--recall) проводится отдельным этапом перед тестированием производительности и показывает среднюю долю совпадения результатов поиска по индексу и полным перебором (от 0 до 1).
Подготовка тестовой выборки из большой таблицы
Важно
Данный этап необходим только в случае отсутствия готовой тестовой выборки и если первичный ключ основной таблицы не является целочисленным, так как в этом случае формирование случайной выборки на лету во время теста не работает.
В этом случае тестовую выборку можно подготовить, выбрав случайные строки из основной таблицы. Ниже приведён пример создания таблицы для хранения тестовой выборки:
CREATE TABLE vector_index_sample (
id Uint64 NOT NULL,
prefix Uint64 NOT NULL,
embedding String NOT NULL,
PRIMARY KEY (id)
);
Наполнение таблицы случайной выборкой приблизительно 1000 строк из большой таблицы:
INSERT INTO vector_index_sample
SELECT id, prefix, embedding FROM large_table
WHERE RandomNumber(id) < 0xFFFFFFFFFFFFFFFF / <число_строк_в_таблице> * 1000;
Совет
Приблизительное число строк в таблице можно посмотреть в статистике таблицы, не выполняя SELECT COUNT(*).