Tarantool против Qdrant и pgvector: честный эксперимент на 1,18 млн векторов


Многие СУБД сегодня поддерживают поиск ближайших соседей, нужный для рекомендательных систем и антифрода. Но на практике системы даже с одинаковым алгоритмом «под капотом» могут решать эту задачу с разной эффективностью: пропускная способность (QPS) и задержки могут сильно различаться из-за накладных расходов движка хранения и модели блокировок. И для бизнеса эта разница может обернуться лишними затратами на инфраструктуру или деградацией UX в пиковые часы. Поэтому к этим параметрам нередко предъявляются особые требования.
Привет, Хабр. Меня зовут Георгий Белянин. В статье я разберу архитектуру векторного поиска в Tarantool и приведу результаты сравнения скорости вставки и запросов с Qdrant и pgvector.
Реализация векторного поиска в Tarantool
В последние годы векторный поиск стал одной из базовых технологий для работы с эмбенддингами. Но современные модели создают векторы размерностью в тысячи измерений, поэтому привычные, классические многомерные индексы не всегда способны эффективно справляться с поставленными задачами.
Исходя из этого мы решили совершенствовать возможности Tarantool — он уже поддерживал многомерный поиск через R-tree, но мы задались вопросом добавления современного ANN-индекса (Approximate Nearest Neighbor, алгоритм приближенного поиска соседей), рассчитанного именно работу с высокоразмерными векторами. И поскольку Tarantool — in-memory OLTP-система с движком memtx, где данные лежат прямо в оперативной памяти, наша гипотеза заключалась в том, что при совмещении быстрого in-memory движка с алгоритмом приближенного поиска соседей можно будет получить современный векторный индекс.
Для своей реализации мы рассматривали несколько вариантов алгоритмов приближенного поиска.
Первая мысль — R-деревья, которые в Tarantool уже есть (R+-tree, R*-tree). R-дерево — это, по сути, многомерное B-дерево: объекты в пространстве ограничиваются «квадратиками» (bounding box), которые объединяются в иерархию. Для OLTP-нагрузок это работает хорошо, но у подхода есть жесткий потолок — приемлемые размерности до ~20 (classic curse of dimensionality). Но нюанс в том, что эмбеддинги современных LLM — это обычно 384, 768, 1024 или 1536 измерений (модели вроде BERT, OpenAI text-embedding и их аналогов). R-дерево на такой размерности просто разваливается.
Далее мы рассмотрели Locality-Sensitive Hashing. Он неплохо сравнивает соседей, распределяя близкие ключи по одним и тем же хеш-бакетам. Но для ANN с требуемым recall в высокой размерности этого недостаточно.
После перешли к изучению HNSW (Hierarchical Navigable Small World). По сути, это многомерный skip-лист: несколько слоев (Layer 0, 1, 2…), переход между которыми дает сначала грубое приближение ответа с большим шагом, а затем итеративное уточнение по мере спуска на нижние уровни. Это не точный поиск, а аппроксимация — но по факту это почти state of the art для ANN-поиска.

В итоге мы остановились на последнем варианте и реализовали архитектуру, в основе которой три компонента:
memtx — самый отлаженный и простой движок Tarantool, данные хранятся построчно в памяти;
USearch — легковесная библиотека для HNSW-индексов (ее, например, использует ClickHouse);
векторный индекс, который подключается через нативный интерфейс Tarantool: указывается размерность, поле, по которому строится индекс, — и дальше это обычный индекс, как любой другой в системе.
Примечание: Индекс написан на C. Поиск — однопоточный.
Сравнение с альтернативными подходами
Мы понимали, что в других решениях для векторного поиска применены другие подходы. Например:
Хранение | Sharding | API | Плюс | Минус | |
Qdrant | RAM + DISK | manual | REST / gRPC | Metadata filtering | Нет транзакций, тяжело тюнить HNSW, не KV/SQL |
Milvus | RAM + DISK | auto | REST / SDK | Multiple ANN, GPU | Тяжелый кластер, overkill для малых систем |
pgvector | RAM + DISK | manual | — | Это просто Postgres | Не такой шустрый |
ClickHouse | RAM + DISK | auto | — | Быстрый exact match, OLAP | Тяжело с большим write |
Redis | RAM | auto | REDIS / REST | Low-latency | Тяжело тюнить индексы |
И здесь стоит погрузиться еще в некоторые детали.
Так, pgvector расширяет синтаксис SQL и добавляет операторы, соответствующие различным метрикам расстояния. Например, оператор <-> используется для вычисления евклидова расстояния между двумя векторами.

Создавайте решения на Tarantool
Ускоряйте цифровые сервисы и снижайте нагрузку на сore‑системы
Таким образом, чтобы найти 10 ближайших векторов к заданному, можно воспользоваться следующим SELECT:
SELECT
id,
content,
embedding <-> '[0.1, 0.2, ...]' AS distance
FROM documents
ORDER BY distance
LIMIT 10;Похожим образом запрос можно сформировать и для ClickHouse. Но в отличие от pgvector, здесь вместо бинарных операторов используются встроенные функции:
SELECT
id,
content,
L2Distance(embedding, [0.1, 0.2, ...]) AS distance
FROM documents
ORDER BY distance
LIMIT 10;С Qdrant чаще работают через REST API или gRPC, поэтому поиск 10 ближайших соседей выглядит как запрос к определенному эндпойнту:
POST /collections/documents/points/search
Content-Type: application/json
{
"vector": [0.1, 0.2, ...],
"limit": 10,
"with_payload": true
}При этом в Tarantool чаще всего использует Lua в качестве языка запросов и языка хранимых процедур. Поэтому аналогичный ANN-поиск выполняется с помощью вызова метода индекса векторного типа:
box.space.documents.index.norm:select(
{1.0, 2.0, ...},
{
iterator = 'neighbor',
limit = 10
}
)То есть Tarantool занимает свою нишу.
Понимая это, мы решили оценить, насколько наша реализация верна и сопоставима по основным параметрам с наиболее распространенными технологиями: Qdrant и pgvector.
Для проведения эксперимента мы взяли за основу официальный бенчмарк от Qdrant и адаптировали его под Tarantool — научили загружать те же батчи данных, что и в остальные системы, чтобы сравнение было честным.
Замеры делали на двух датасетах:
dbpedia-openai-100K-1536-angular — 100 тысяч векторов, 1536 измерений (акцент на размерности);
glove-100 — 1,18 млн векторов, 100 измерений (акцент на количестве).
Все тестировалось in-memory. Метрика на поиске — it/s (queries per second). Индексы у всех участников настраивались одинаково, поэтому и точность (recall) получилась сопоставимая.
Результаты эксперимента
Результаты замеров показали следующее:
На датасете с высокой размерностью (100K, dim=1536) Tarantool показал 196 it/s против 176 it/s у Qdrant (+11%) и 82 it/s у pgvector (в 2,4 раза быстрее);
На датасете с большим числом векторов (1,18M, dim=100) Tarantool показал 800 it/s против 532 it/s у Qdrant и всего 86 it/s у pgvector. Это +50% к Qdrant и почти в 9,3 раза быстрее pgvector.

Такой результат связан с тем, что у Tarantool данные целиком находятся в оперативной памяти, а быстрый HNSW-индекс дополняется шустрым low-latency OLTP-движком. В итоге Tarantool легко проводит разнородные вычисления, а на большом числе векторов этот эффект масштабируется сильнее, чем на большой размерности одного вектора.
А вот со вставкой все наоборот:
На 100K векторов, 1536 измерений — 43 секунды у Tarantool против 19 у Qdrant (в 2,3 раза дольше) и 21 у pgvector (в 2 раза дольше).
На 1,18M векторов Tarantool грузит данные 150 секунд — против 57 у Qdrant (в 2,6 раза дольше) и 55 у pgvector (в 2,7 раза дольше).

Такие показатели Tarantool в подобных задачах обусловлены использованием библиотеки USearch, которая показывает тяжеловесную вставку. В итоге на добавление записи и перестройку индекса уходит заметно больше времени, чем у конкурентов.
Но в целом логика здесь тоже объяснимая: если упростить вставку (как это делают Qdrant и pgvector), то платить приходится на чтении — за счет того, что приходится сканировать. Tarantool выбрал обратный компромисс: тяжелая вставка ради быстрого скана.
Примечание: Репозиторий с реализацией доступен на GitHub, поэтому при желании эксперимент можно воспроизвести или использовать как отправную точку для собственных тестов.
Краткое послесловие
Проведенное исследование предсказуемо показало, что наша реализация — не «серебряная пуля» и не подходит для ситуаций, когда критична быстрая массовая загрузка данных или требуется частая актуализация векторов. Вместе с тем наш подход дает ощутимый выигрыш там, где на первый план выходит скорость поиска и тесная интеграция с транзакционной логикой.
И здесь кроется важный инсайт: результаты тестов подтвердили, что для ряда задач совсем не обязательно разворачивать отдельную векторную БД — зачастую для хранения векторов и бизнес‑данных вполне можно ограничиться одной системой, такой как Tarantool, сохранив при этом целостность операций и упростив общую архитектуру.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.