Кэш запросов хранит сжатые наборы результатов в памяти и повторно использует их для последующих запросов, когда это возможно. Вы можете настроить его с помощью следующих директив:
- qcache_max_bytes — ограничение на использование RAM для хранения кэшированных запросов. По умолчанию установлено в 16 МБ. Установка
qcache_max_bytesв 0 полностью отключает кэш запросов. - qcache_thresh_msec — минимальное время выполнения запроса в миллисекундах для кеширования. Запросы, которые выполняются быстрее этого времени, не будут кешироваться. По умолчанию 3000 мс, или 3 секунды.
- qcache_ttl_sec — время жизни кэшированной записи, или TTL. Запросы будут оставаться в кэше в течение этого времени. По умолчанию 60 секунд, или 1 минута.
Эти настройки можно изменить на лету, используя оператор SET GLOBAL:
mysql> SET GLOBAL qcache_max_bytes=128000000;
Эти изменения применяются немедленно, и кэшированные наборы результатов, которые больше не соответствуют ограничениям, сразу же отбрасываются. При уменьшении размера кэша на лету выигрыш получают наиболее недавно использованные (MRU) наборы результатов.
Кэш запросов работает следующим образом. При включении каждый результат полнотекстового поиска полностью сохраняется в памяти. Это происходит после полнотекстового совпадения, фильтрации и ранжирования, так что по сути мы сохраняем пары {docid,weight} для total_found. Сжатые совпадения могут занимать в среднем от 2 до 12 байт на совпадение, в основном в зависимости от дельт между последовательными docid. По завершении запроса мы проверяем пороги времени и размера, и либо сохраняем сжатый набор результатов для повторного использования, либо отбрасываем его.
Обратите внимание, что влияние кэша запросов на RAM не ограничивается qcache_max_bytes! Например, если у вас выполняется 10 одновременных запросов, каждый из которых находит до 1 млн совпадений (после фильтров), то пиковое временное использование RAM окажется в диапазоне от 40 МБ до 240 МБ, даже если запросы достаточно быстрые и не кэшируются.
Запросы могут использовать кэш, когда совпадают таблица, полнотекстовый запрос (то есть содержимое MATCH()), ранжировщик и совместимы фильтры. Это значит:
- Полнотекстовая часть внутри
MATCH()должна совпадать посимвольно. Добавьте один пробел — и это уже другой запрос, с точки зрения кэша запросов. - Ранжировщик (и его параметры, если есть, для пользовательских ранжировщиков) должен совпадать посимвольно.
- Фильтры должны быть надмножеством оригинальных фильтров. Вы можете добавить дополнительные фильтры и все равно попасть в кэш. (В этом случае дополнительные фильтры будут применены к кэшированному результату.) Но если вы уберёте какой-то фильтр, это уже будет новый запрос.
Записи кэша истекают по TTL и также инвалидируются при ротации таблиц, или при выполнении TRUNCATE, или ATTACH. Обратите внимание, что в настоящее время записи не инвалидируются при произвольных записях в RT-таблицу! Поэтому кэшированный запрос может возвращать старые результаты в течение времени жизни TTL.
Вы можете проверить текущий статус кэша с помощью SHOW STATUS через переменные qcache_XXX:
mysql> SHOW STATUS LIKE 'qcache%';
+-----------------------+----------+
| Counter | Value |
+-----------------------+----------+
| qcache_max_bytes | 16777216 |
| qcache_thresh_msec | 3000 |
| qcache_ttl_sec | 60 |
| qcache_cached_queries | 0 |
| qcache_used_bytes | 0 |
| qcache_hits | 0 |
+-----------------------+----------+
6 rows in set (0.00 sec)
Сортировки в первую очередь влияют на сравнения строковых атрибутов. Они определяют как кодировку набора символов, так и стратегию, которую Manticore использует для сравнения строк при выполнении ORDER BY или GROUP BY с участием строкового атрибута.
Строковые атрибуты хранятся в неизменном виде во время индексирования, и к ним не прикрепляется информация о наборе символов или языке. Это приемлемо, пока Manticore нужно лишь хранить и возвращать строки вызывающему приложению дословно. Однако, когда вы просите Manticore отсортировать по строковому значению, запрос сразу же становится неоднозначным.
Во-первых, строки с одним байтом (ASCII, ISO-8859-1 или Windows-1251) требуют иной обработки, чем строки UTF-8, которые могут кодировать каждый символ переменным числом байт. Поэтому нам нужно знать тип набора символов, чтобы правильно интерпретировать сырые байты как осмысленные символы.
Во-вторых, нам также необходимо знать правила сортировки, специфичные для языка. Например, при сортировке по правилам США в локали en_US, акцентированный символ ï (малая буква i с диарезой) должен размещаться где-то после z. Однако при сортировке с учётом французских правил и локали fr_FR, его следует поместить между i и j. Другой набор правил может вовсе игнорировать акценты, позволяя ï и i смешиваться произвольно.
В-третьих, в некоторых случаях требуется чувствительная к регистру сортировка, а в других — регистронезависимая.
Сортировки инкапсулируют всё перечисленное: набор символов, языковые правила и чувствительность к регистру. В настоящее время Manticore предоставляет четыре сортировки:
libc_cilibc_csutf8_general_cibinary
Первые две сортировки опираются на несколько стандартных вызовов библиотеки C (libc) и, таким образом, могут поддерживать любую локаль, установленную в вашей системе. Они обеспечивают регистронезависимые (_ci) и регистрозависимые (_cs) сравнения соответственно. По умолчанию используется локаль C, что фактически сводит сортировку к побайтовому сравнению. Чтобы изменить это, необходимо указать другую доступную локаль с помощью директивы collation_libc_locale. Список локалей, доступных в вашей системе, обычно можно получить с помощью команды locale:
$ locale -a
C
en_AG
en_AU.utf8
en_BW.utf8
en_CA.utf8
en_DK.utf8
en_GB.utf8
en_HK.utf8
en_IE.utf8
en_IN
en_NG
en_NZ.utf8
en_PH.utf8
en_SG.utf8
en_US.utf8
en_ZA.utf8
en_ZW.utf8
es_ES
fr_FR
POSIX
ru_RU.utf8
ru_UA.utf8
Конкретный список системных локалей может варьироваться. Обратитесь к документации вашей ОС для установки дополнительных нужных локалей.
Локали utf8_general_ci и binary встроены в Manticore. Первая — это универсальная сортировка для UTF-8 данных (без так называемой языковой адаптации); она должна вести себя аналогично сортировке utf8_general_ci в MySQL. Вторая — простое побайтовое сравнение.
Сортировка может быть переопределена через SQL на уровне сессии с помощью оператора SET collation_connection. Все последующие SQL-запросы будут использовать эту сортировку. В противном случае все запросы будут использовать сортировку, установленную по умолчанию на сервере, или указанную в конфигурационной директиве collation_server. В настоящее время по умолчанию в Manticore используется сортировка libc_ci.
Сортировки влияют на все сравнения строковых атрибутов, включая сортировки в ORDER BY и GROUP BY, поэтому можно получить результаты, отсортированные или сгруппированные по-разному в зависимости от выбранной сортировки. Обратите внимание, что сортировки не влияют на полнотекстовый поиск; для этого используйте charset_table.
Когда Manticore выполняет полносканирующий запрос, он может либо использовать простой скан для проверки каждого документа с учётом фильтров, либо применять дополнительные данные и/или алгоритмы для ускорения выполнения запроса. Manticore использует оптимизатор на основе стоимости (CBO), также известный как «оптимизатор запросов», для определения подходящего способа.
CBO также может улучшать производительность полнотекстовых запросов. Подробнее см. ниже.
CBO может решить заменить один или несколько фильтров запроса одним из следующих элементов, если он определит, что это улучшит производительность:
- docid индекс использует специальный вторичный индекс только docid, хранящийся в файлах с расширением
.spt. Помимо улучшения фильтров по идентификаторам документов, docid индекс также используется для ускорения поиска идентификатора строки по идентификатору документа и для ускорения применения больших killlist при запуске демона. - колоночное сканирование опирается на колоночное хранение и может использоваться только на колоночном атрибуте. Оно сканирует каждое значение и проверяет его по фильтру, но при этом сильно оптимизировано и обычно быстрее подхода по умолчанию.
- вторичные индексы создаются по умолчанию для всех атрибутов (кроме JSON). Они используют PGM индекс вместе с встроенным инвертированным индексом Manticore для получения списка идентификаторов строк, соответствующих значению или диапазону значений. Вторичные индексы хранятся в файлах с расширениями
.spidxи.spjidx. Для информации о том, как создавать вторичные индексы по JSON атрибутам, см. json_secondary_indexes.
Оптимизатор оценивает стоимость каждого пути выполнения, используя различные статистики атрибутов, включая:
- Информацию о распределении данных внутри атрибута (гистограммы, хранящиеся в файлах
.sphi). Гистограммы создаются автоматически при индексации данных и служат основным источником информации для CBO. - Информацию от PGM (вторичных индексов), которая помогает оценить количество списков документов для чтения. Это помогает оценить производительность объединения doclist и выбрать подходящий алгоритм слияния (слияние с приоритетной очередью или слияние битмапов).
- Статистику кодирования колонок, используемую для оценки производительности декомпрессии колоночных данных.
- Колоночное дерево min-max. В то время как CBO использует гистограммы для оценки количества документов, остающихся после применения фильтра, он также должен определить, сколько документов фильтр пришлось обработать. Для колоночных атрибутов частичная оценка min-max дерева служит этой цели.
- Полнотекстовый словарь. CBO использует статистику терминов для оценки стоимости вычисления полнотекстового дерева.
Оптимизатор вычисляет стоимость выполнения для каждого фильтра, используемого в запросе. Поскольку некоторые фильтры могут быть заменены несколькими разными элементами (например, для идентификатора документа Manticore может использовать простой скан, поиск по docid индексу, колоночное сканирование (если идентификатор документа колоночный) и вторичный индекс), оптимизатор оценивает все доступные комбинации. Однако существует максимальный лимит в 1024 комбинации.
Для оценки стоимости выполнения запроса оптимизатор рассчитывает предполагаемые стоимости наиболее значимых операций, выполняемых при выполнении запроса. Он использует предустановленные константы для представления стоимости каждой операции.
Оптимизатор сравнивает стоимости каждого пути выполнения и выбирает путь с наименьшей стоимостью для выполнения запроса.
При работе с полнотекстовыми запросами, которые содержат фильтры по атрибутам, оптимизатор запросов выбирает один из двух возможных путей выполнения. Либо выполнить полнотекстовый запрос, получить совпадения и применить фильтры. Либо заменить фильтры одним или несколькими элементами, описанными выше, получить из них rowid и внедрить их в полнотекстовое дерево. Таким образом результаты полнотекстового поиска пересекутся с результатами полносканирования. Оптимизатор оценивает стоимость вычисления полнотекстового дерева и наилучший возможный путь вычисления результатов фильтра. Используя эту информацию, оптимизатор выбирает путь выполнения.
Ещё один фактор — многопоточное выполнение запросов (когда включён pseudo_sharding). CBO знает, что некоторые запросы могут выполняться в нескольких потоках, и учитывает это. CBO отдаёт предпочтение более короткому времени выполнения запроса (то есть задержке) по сравнению с пропускной способностью. Например, если запрос с использованием колоночного сканирования может быть выполнен в нескольких потоках (и занять несколько ядер CPU) и при этом быстрее, чем запрос, выполненный в одном потоке с использованием вторичных индексов, будет предпочтительным многопоточное выполнение.
Запросы с использованием вторичных индексов и docid индексов всегда выполняются в одном потоке, поскольку бенчмарки показывают, что многопоточность для них малоэффективна.
На данный момент оптимизатор учитывает только затраты CPU и не принимает во внимание использование памяти или диска.
Manticore Search поддерживает возможность добавления эмбеддингов, сгенерированных моделями машинного обучения, к каждому документу, а затем выполнение поиска ближайших соседей по ним. Это позволяет создавать такие функции, как поиск по сходству, рекомендации, семантический поиск и ранжирование по релевантности на основе алгоритмов NLP, среди прочего, включая поиск по изображениям, видео и звуку.
Эмбеддинг — это метод представления данных — таких как текст, изображения или звук — в виде векторов в многомерном пространстве. Эти векторы созданы таким образом, чтобы расстояние между ними отражало сходство представляемых ими данных. Этот процесс обычно использует такие алгоритмы, как word embeddings (например, Word2Vec, BERT) для текста или нейронные сети для изображений. Многомерная природа векторного пространства, с большим количеством компонентов на вектор, позволяет представлять сложные и тонкие взаимосвязи между элементами. Их сходство измеряется расстоянием между этими векторами, часто с использованием таких методов, как евклидово расстояние или косинусное сходство.
Manticore Search позволяет выполнять поиск по векторам методом k-ближайших соседей (KNN) с использованием библиотеки HNSW. Эта функциональность является частью Manticore Columnar Library.
Для выполнения KNN-поиска необходимо сначала настроить вашу таблицу. Векторы с плавающей точкой и KNN-поиск поддерживаются только в реальном времени (не в обычных таблицах). Таблица должна иметь хотя бы один атрибут типа float_vector, который служит вектором данных. Необходимо указать следующие свойства:
-
knn_type: Обязательная настройка; в настоящее время поддерживается толькоhnsw. -
knn_dims: Обязательная настройка, которая определяет размерность индексируемых векторов. -
hnsw_similarity: Обязательная настройка, которая определяет функцию расстояния, используемую индексом HNSW. Допустимые значения:L2- Квадрат L2IP- Скалярное произведениеCOSINE- Косинусное сходство
Примечание: При использовании сходства
COSINEвекторы автоматически нормализуются при вставке. Это означает, что сохраненные значения векторов могут отличаться от исходных входных значений, так как они будут преобразованы в единичные векторы (векторы с математической длиной/величиной 1.0) для обеспечения эффективных вычислений косинусного сходства. Эта нормализация сохраняет направление вектора, стандартизируя его длину. -
hnsw_m: Необязательная настройка, определяющая максимальное количество исходящих соединений в графе. По умолчанию 16. -
hnsw_ef_construction: Необязательная настройка, определяющая компромисс между временем построения и точностью. По умолчанию 200.
- SQL
- Config
create table test ( title text, image_vector float_vector knn_type='hnsw' knn_dims='4' hnsw_similarity='l2' );table test_vec {
type = rt
...
rt_attr_float_vector = image_vector
knn = {"attrs":[{"name":"image_vector","type":"hnsw","dims":4,"hnsw_similarity":"L2","hnsw_m":16,"hnsw_ef_construction":200}]}
}Примечание: Для автоэмбеддингов в обычном режиме см. пример ниже, который показывает, как использовать параметры model_name и from в конфигурации knn.
Query OK, 0 rows affected (0.01 sec)Самый простой способ работы с векторными данными — использование автоэмбеддингов. С этой функцией вы создаете таблицу с параметрами MODEL_NAME и FROM, а затем просто вставляете свои текстовые данные — Manticore автоматически генерирует эмбеддинги для вас.
При создании таблицы для автоэмбеддингов укажите:
MODEL_NAME: Модель эмбеддинга для использованияFROM: Какие поля использовать для генерации эмбеддингов (пустое значение означает все текстовые/строковые поля)
Поддерживаемые модели эмбеддингов:
- Sentence Transformers: Любая подходящая модель на основе BERT из Hugging Face (например,
sentence-transformers/all-MiniLM-L6-v2) — ключ API не требуется. Manticore загружает модель при создании таблицы. - Qwen локальные эмбеддинги: Модели эмбеддингов Qwen, такие как
Qwen/Qwen3-Embedding-0.6B— ключ API не требуется. Manticore загружает модель при создании таблицы. - OpenAI: Модели эмбеддингов OpenAI, такие как
openai/text-embedding-ada-002- требует параметрAPI_KEY='<OPENAI_API_KEY>' - Voyage: Модели эмбеддингов Voyage AI - требует параметр
API_KEY='<VOYAGE_API_KEY>' - Jina: Модели эмбеддингов Jina AI - требует параметр
API_KEY='<JINA_API_KEY>'
Более подробную информацию о настройке атрибута float_vector можно найти здесь.
- SQL
- Config
Использование sentence-transformers (ключ API не требуется)
CREATE TABLE products (
title TEXT,
description TEXT,
embedding_vector FLOAT_VECTOR KNN_TYPE='hnsw' HNSW_SIMILARITY='l2'
MODEL_NAME='sentence-transformers/all-MiniLM-L6-v2' FROM='title'
);Использование локальных эмбеддингов Qwen (ключ API не требуется)
CREATE TABLE products_qwen (
title TEXT,
description TEXT,
embedding_vector FLOAT_VECTOR KNN_TYPE='hnsw' HNSW_SIMILARITY='l2'
MODEL_NAME='Qwen/Qwen3-Embedding-0.6B' FROM='title' CACHE_PATH='/opt/homebrew/var/manticore/.cache/manticore'
);Использование OpenAI (требуется параметр API_KEY)
CREATE TABLE products_openai (
title TEXT,
description TEXT,
embedding_vector FLOAT_VECTOR KNN_TYPE='hnsw' HNSW_SIMILARITY='l2'
MODEL_NAME='openai/text-embedding-ada-002' FROM='title,description' API_KEY='...'
);Использование всех текстовых полей для эмбеддингов (FROM пуст)
CREATE TABLE products_all (
title TEXT,
description TEXT,
embedding_vector FLOAT_VECTOR KNN_TYPE='hnsw' HNSW_SIMILARITY='l2'
MODEL_NAME='sentence-transformers/all-MiniLM-L6-v2' FROM=''
);table products {
type = rt
path = /path/to/products
rt_field = title
rt_field = description
rt_attr_float_vector = embedding_vector
knn = {"attrs":[{"name":"embedding_vector","type":"hnsw","hnsw_similarity":"L2","hnsw_m":16,"hnsw_ef_construction":200,"model_name":"sentence-transformers/all-MiniLM-L6-v2","from":"title"}]}
}Использование OpenAI с ключом API в обычном режиме:
table products_openai {
type = rt
path = /path/to/products_openai
rt_field = title
rt_field = description
rt_attr_float_vector = embedding_vector
knn = {"attrs":[{"name":"embedding_vector","type":"hnsw","hnsw_similarity":"L2","hnsw_m":16,"hnsw_ef_construction":200,"model_name":"openai/text-embedding-ada-002","from":"title,description","api_key":"your-api-key-here"}]}
}Использование всех текстовых полей (пустой FROM):
table products_all {
type = rt
path = /path/to/products_all
rt_field = title
rt_field = description
rt_attr_float_vector = embedding_vector
knn = {"attrs":[{"name":"embedding_vector","type":"hnsw","hnsw_similarity":"L2","hnsw_m":16,"hnsw_ef_construction":200,"model_name":"sentence-transformers/all-MiniLM-L6-v2","from":""}]}
}Важные примечания для обычного режима:
- При использовании
model_nameвы не должны указыватьdims— модель автоматически определяет размерность векторов. Параметрыdimsиmodel_nameявляются взаимоисключающими. - Когда не используется
model_name(ручная вставка векторов), вы должны указатьdims, чтобы обозначить размерность векторов. - Параметр
fromуказывает, какие поля использовать для генерации эмбеддингов (список, разделенный запятыми, или пустая строка для всех текстовых/строковых полей). Этот параметр обязателен при использованииmodel_name. - Для моделей на основе API (OpenAI, Voyage, Jina) включите параметр
api_keyв конфигурацию knn
При использовании автоэмбеддингов не указывайте векторное поле в вашем операторе INSERT. Эмбеддинги генерируются автоматически из текстовых полей, указанных в параметре FROM.
- SQL
Вставка только текстовых данных - эмбеддинги генерируются автоматически
INSERT INTO products (title) VALUES
('machine learning artificial intelligence'),
('banana fruit sweet yellow');Вставка нескольких полей - оба используются для эмбеддинга, если FROM='title,description'
INSERT INTO products_openai (title, description) VALUES
('smartphone', 'latest mobile device with advanced features'),
('laptop', 'portable computer for work and gaming');Вставка пустого вектора (документ исключен из векторного поиска)
INSERT INTO products (title, embedding_vector) VALUES
('no embedding item', ());Поиск работает аналогичным образом - предоставьте ваш запрос в виде текста, и Manticore сгенерирует эмбеддинги и найдет похожие документы:
- SQL
- JSON
SELECT id, knn_dist() FROM products WHERE knn(embedding_vector, 3, 'machine learning');Использование текстового запроса с авто-эмбеддингами
POST /search
{
"table": "products",
"knn": {
"field": "embedding_vector",
"query": "machine learning",
"k": 3
}
}Использование векторного запроса напрямую
POST /search
{
"table": "products",
"knn": {
"field": "embedding_vector",
"query": [0.1, 0.2, 0.3, 0.4],
"k": 3
}
}+------+------------+
| id | knn_dist() |
+------+------------+
| 1 | 0.12345678 |
| 2 | 0.87654321 |
+------+------------+
2 rows in set (0.00 sec){
"took": 0,
"timed_out": false,
"hits": {
"total": 2,
"total_relation": "eq",
"hits": [
{
"_id": 1,
"_score": 1,
"_knn_dist": 0.12345678,
"_source": {
"title": "machine learning artificial intelligence"
}
},
{
"_id": 2,
"_score": 1,
"_knn_dist": 0.87654321,
"_source": {
"title": "banana fruit sweet yellow"
}
}
]
}
}В качестве альтернативы, вы можете вручную вставлять предварительно вычисленные векторные данные, убедившись, что они соответствуют размерности, указанной вами при создании таблицы. Вы также можете вставить пустой вектор; это означает, что документ будет исключен из результатов векторного поиска.
Важно: При использовании hnsw_similarity='cosine' векторы автоматически нормализуются при вставке до единичных векторов (векторов с математической длиной/величиной, равной 1.0). Эта нормализация сохраняет направление вектора, стандартизируя его длину, что необходимо для эффективных вычислений косинусного сходства. Это означает, что сохраненные значения будут отличаться от ваших исходных входных значений.
- SQL
- JSON
insert into test values ( 1, 'yellow bag', (0.653448,0.192478,0.017971,0.339821) ), ( 2, 'white bag', (-0.148894,0.748278,0.091892,-0.095406) );POST /insert
{
"table":"test_vec",
"id":1,
"doc": { "title" : "yellow bag", "image_vector" : [0.653448,0.192478,0.017971,0.339821] }
}
POST /insert
{
"table":"test_vec",
"id":2,
"doc": { "title" : "white bag", "image_vector" : [-0.148894,0.748278,0.091892,-0.095406] }
}Query OK, 2 rows affected (0.00 sec){
"table":"test",
"_id":1,
"created":true,
"result":"created",
"status":201
}
{
"table":"test",
"_id":2,
"created":true,
"result":"created",
"status":201
}Теперь вы можете выполнять KNN поиск, используя предложение knn в формате SQL или JSON. Оба интерфейса поддерживают одинаковые основные параметры, обеспечивая согласованный опыт независимо от выбранного формата:
- SQL:
select ... from <table name> where knn ( <field>, <query vector> [,<options>] ) - JSON:
POST /search { "table": "<table name>", "knn": { "field": "<field>", "query": "<text or vector>", "ef": <ef>, "rescore": <rescore>, "oversampling": <oversampling> } }
Параметры:
field: Это имя атрибута вектора с плавающей запятой, содержащего векторные данные.k: Устаревшая опция. Вместо этого используйтеlimitв запросе. Ранее использовалась для указания количества документов, которое должен возвращать один индекс HNSW. Однако фактическое количество документов, включенных в окончательные результаты, может отличаться. Например, если система работает с таблицами реального времени, разделенными на дисковые чанки, каждый чанк может возвращатьkдокументов, что приводит к общему количеству, превышающему указанноеk(так как совокупное количество будетnum_chunks * k). С другой стороны, окончательное количество документов может быть меньшеk, если после запросаkдокументов некоторые из них отфильтровываются на основе определенных атрибутов. Важно отметить, что параметрkне применяется к ramchunks. В контексте ramchunks процесс извлечения работает иначе, и поэтому влияние параметраkна количество возвращаемых документов неприменимо.query: (Рекомендуемый параметр) Поисковый запрос, который может быть:- Текстовой строкой: Автоматически преобразуется в эмбеддинги, если для поля настроены авто-эмбеддинги. Вернет ошибку, если у поля нет авто-эмбеддингов.
- Векторным массивом: Работает так же, как
query_vector.
query_vector: (Устаревший параметр) Поисковый вектор в виде массива чисел. Все еще поддерживается для обратной совместимости. Примечание: Используйте либоquery, либоquery_vector, но не оба в одном запросе.ef: необязательный размер динамического списка, используемого во время поиска. Более высокое значениеefприводит к более точному, но более медленному поиску. По умолчанию равно 10.rescore: Включает пересчет оценок KNN (включено по умолчанию). Установите0в SQL илиfalseв JSON, чтобы отключить пересчет. После завершения KNN поиска с использованием квантованных векторов (с возможным перевыборкой), расстояния пересчитываются с исходными (полноразрядными) векторами, и результаты пересортировываются для повышения точности ранжирования.oversampling: Устанавливает коэффициент (значение с плавающей запятой), на который умножаетсяkпри выполнении KNN поиска, что приводит к извлечению большего количества кандидатов, чем необходимо, с использованием квантованных векторов. По умолчанию применяетсяoversampling=3.0. Эти кандидаты могут быть позже переоценены, если пересчет оценок включен. Перевыборка также работает с неквантованными векторами. Поскольку она увеличиваетk, что влияет на работу индекса HNSW, это может вызвать небольшое изменение точности результатов.
Документы всегда сортируются по расстоянию до поискового вектора. Любые дополнительные критерии сортировки, которые вы укажете, будут применены после этого основного условия сортировки. Для получения расстояния существует встроенная функция knn_dist().
- SQL
- JSON
select id, knn_dist() from test where knn ( image_vector, (0.286569,-0.031816,0.066684,0.032926), { ef=2000, oversampling=3.0, rescore=1 } );POST /search
{
"table": "test",
"knn":
{
"field": "image_vector",
"query": [0.286569,-0.031816,0.066684,0.032926],
"ef": 2000,
"rescore": true,
"oversampling": 3.0
}
}+------+------------+
| id | knn_dist() |
+------+------------+
| 1 | 0.28146550 |
| 2 | 0.81527930 |
+------+------------+
2 rows in set (0.00 sec){
"took":0,
"timed_out":false,
"hits":
{
"total":2,
"total_relation":"eq",
"hits":
[
{
"_id": 1,
"_score":1,
"_knn_dist":0.28146550,
"_source":
{
"title":"yellow bag",
"image_vector":[0.653448,0.192478,0.017971,0.339821]
}
},
{
"_id": 2,
"_score":1,
"_knn_dist":0.81527930,
"_source":
{
"title":"white bag",
"image_vector":[-0.148894,0.748278,0.091892,-0.095406]
}
}
]
}
}Индексы HNSW должны быть полностью загружены в память для выполнения KNN поиска, что может привести к значительному потреблению памяти. Для уменьшения использования памяти может применяться скалярное квантование - техника, которая сжимает высокоразмерные векторы, представляя каждый компонент (размерность) ограниченным количеством дискретных значений. Manticore поддерживает 8-битное и 1-битное квантование, что означает, что каждый компонент вектора сжимается с 32-битного числа с плавающей запятой до 8 бит или даже 1 бита, уменьшая использование памяти в 4 или 32 раза соответственно. Эти сжатые представления также позволяют выполнять более быстрые вычисления расстояний, так как больше компонентов вектора может быть обработано одной инструкцией SIMD. Хотя скалярное квантование вносит некоторую ошибку аппроксимации, это часто является оправданным компромиссом между точностью поиска и эффективностью использования ресурсов. Для еще лучшей точности квантование можно комбинировать с пересчетом оценок и перевыборкой: извлекается больше кандидатов, чем запрошено, и расстояния для этих кандидатов пересчитываются с использованием исходных 32-битных векторов с плавающей запятой.
Поддерживаемые типы квантования включают:
8bit: Каждый компонент вектора квантуется до 8 бит.1bit: Каждый компонент вектора квантуется до 1 бита. Используется асимметричное квантование, при этом векторы запросов квантуются до 4 бит, а хранимые векторы — до 1 бита. Этот подход обеспечивает более высокую точность по сравнению с более простыми методами, хотя и с некоторым компромиссом в производительности.1bitsimple: Каждый компонент вектора квантуется до 1 бита. Этот метод быстрее, чем1bit, но обычно менее точен.
- SQL
create table test ( title text, image_vector float_vector knn_type='hnsw' knn_dims='4' hnsw_similarity='l2' quantization='1bit');Query OK, 0 rows affected (0.01 sec)ПРИМЕЧАНИЕ: Поиск похожих документов по id требует наличия Manticore Buddy. Если это не работает, убедитесь, что Buddy установлен.
Поиск документов, похожих на конкретный, на основе его уникального ID, является распространённой задачей. Например, когда пользователь просматривает определённый элемент, Manticore Search может эффективно идентифицировать и отобразить список элементов, наиболее похожих на него в векторном пространстве. Вот как это можно сделать:
- SQL:
select ... from <table name> where knn ( <field>, <k>, <document id> ) - JSON:
POST /search { "table": "<table name>", "knn": { "field": "<field>", "doc_id": <document id>, "k": <k> } }
Параметры:
field: Это имя атрибута вектора с плавающей точкой, содержащего векторные данные.k: Это количество возвращаемых документов и ключевой параметр для индексов Hierarchical Navigable Small World (HNSW). Он указывает количество документов, которое должен вернуть один индекс HNSW. Однако фактическое количество документов, включённых в окончательные результаты, может варьироваться. Например, если система работает с таблицами реального времени, разделёнными на дисковые чанки, каждый чанк может вернутьkдокументов, что приводит к общему количеству, превышающему указанноеk(так как совокупное количество будетnum_chunks * k). С другой стороны, итоговое количество документов может быть меньшеk, если после запросаkдокументов некоторые из них отфильтровываются на основе определённых атрибутов. Важно отметить, что параметрkне применяется к ramchunks. В контексте ramchunks процесс извлечения работает иначе, и, следовательно, влияние параметраkна количество возвращаемых документов неприменимо.document id: ID документа для поиска сходства KNN.
- SQL
- JSON
select id, knn_dist() from test where knn ( image_vector, 5, 1 );POST /search
{
"table": "test",
"knn":
{
"field": "image_vector",
"doc_id": 1,
"k": 5
}
}+------+------------+
| id | knn_dist() |
+------+------------+
| 2 | 0.81527930 |
+------+------------+
1 row in set (0.00 sec){
"took":0,
"timed_out":false,
"hits":
{
"total":1,
"total_relation":"eq",
"hits":
[
{
"_id": 2,
"_score":1643,
"_knn_dist":0.81527930,
"_source":
{
"title":"white bag",
"image_vector":[-0.148894,0.748278,0.091892,-0.095406]
}
}
]
}
}Manticore также поддерживает дополнительную фильтрацию документов, возвращаемых поиском KNN, либо по полнотекстовому соответствию, либо по фильтрам атрибутов, либо по обоим.
- SQL
- JSON
select id, knn_dist() from test where knn ( image_vector, 5, (0.286569,-0.031816,0.066684,0.032926) ) and match('white') and id < 10;POST /search
{
"table": "test",
"knn":
{
"field": "image_vector",
"query": [0.286569,-0.031816,0.066684,0.032926],
"k": 5,
"filter":
{
"bool":
{
"must":
[
{ "match": {"_all":"white"} },
{ "range": { "id": { "lt": 10 } } }
]
}
}
}
}+------+------------+
| id | knn_dist() |
+------+------------+
| 2 | 0.81527930 |
+------+------------+
1 row in set (0.00 sec){
"took":0,
"timed_out":false,
"hits":
{
"total":1,
"total_relation":"eq",
"hits":
[
{
"_id": 2,
"_score":1643,
"_knn_dist":0.81527930,
"_source":
{
"title":"white bag",
"image_vector":[-0.148894,0.748278,0.091892,-0.095406]
}
}
]
}
}