Параметры поиска

SQL SELECT оператор и HTTP /search эндпоинт поддерживают ряд опций, которые можно использовать для тонкой настройки поведения поиска.

OPTION

Общий синтаксис

SQL:

SELECT ... [OPTION <optionname>=<value> [ , ... ]] [/*+ [NO_][ColumnarScan|DocidIndex|SecondaryIndex(<attribute>[,...])]] /*]

HTTP:

POST /search
{
    "table" : "table_name",
    "options":
    {
        "optionname": "value",
        "optionname2": <value2>
    }
}
‹›
  • SQL
  • JSON
📋
SELECT * FROM test WHERE MATCH('@title hello @body world')
OPTION ranker=bm25, max_matches=3000,
field_weights=(title=10, body=3), agent_query_timeout=10000
‹›
Response
+------+-------+-------+
| id   | title | body  |
+------+-------+-------+
|    1 | hello | world |
+------+-------+-------+
1 row in set (0.00 sec)

Поддерживаемые опции:

accurate_aggregation

Целое число. Включает или отключает гарантированную точность агрегатов при выполнении запросов groupby в нескольких потоках. По умолчанию 0.

При выполнении запроса groupby он может выполняться параллельно на простой таблице с несколькими псевдо-шардами (если включен pseudo_sharding). Аналогичный подход работает с RT таблицами. Каждый шард/чанк выполняет запрос, но количество групп ограничено max_matches. Если наборы результатов из разных шардов/чанков содержат разные группы, подсчёты групп и агрегаты могут быть неточными. Обратите внимание, что Manticore пытается увеличить max_matches до max_matches_increase_threshold на основе количества уникальных значений атрибута groupby (получаемых из вторичных индексов). Если это удаётся, потери точности не будет.

Однако, если количество уникальных значений атрибута groupby велико, дальнейшее увеличение max_matches может быть не лучшей стратегией, так как это может привести к снижению производительности и увеличению использования памяти. Установка accurate_aggregation в 1 заставляет groupby-запросы выполняться в одном потоке, что решает проблему точности. Обратите внимание, что выполнение в одном потоке принудительно только тогда, когда max_matches нельзя установить достаточно высоким; в противном случае запросы с accurate_aggregation=1 всё равно будут выполняться в нескольких потоках.

В целом, установка accurate_aggregation в 1 обеспечивает точность подсчёта групп и агрегатов в RT таблицах и простых таблицах с pseudo_sharding=1. Недостаток в том, что запросы будут выполняться медленнее, так как будут вынуждены работать в одном потоке.

Однако, если у нас есть RT таблица и простая таблица с одинаковыми данными, и мы выполняем запрос с accurate_aggregation=1, мы всё равно можем получить разные результаты. Это происходит потому, что демон может выбрать разные настройки max_matches для RT и простой таблицы из-за настройки max_matches_increase_threshold.

agent_query_timeout

Целое число. Максимальное время в миллисекундах ожидания завершения удалённых запросов, см. этот раздел.

boolean_simplify

0 или 1 (по умолчанию 1). boolean_simplify=1 включает упрощение запроса для ускорения его выполнения.

Эту опцию также можно установить глобально в конфигурации searchd, чтобы изменить поведение по умолчанию для всех запросов. Опция на уровне запроса переопределит глобальную настройку.

comment

Строка, пользовательский комментарий, который копируется в файл журнала запросов.

cutoff

Целое число. Указывает максимальное количество обрабатываемых совпадений. Если не задано, Manticore автоматически выберет подходящее значение.

  • N = 0: Отключает ограничение на количество совпадений.
  • N > 0: Инструктирует Manticore прекратить обработку результатов, как только будет найдено N совпадающих документов.
  • Не задано: Manticore самостоятельно определяет порог.

Когда Manticore не может определить точное количество совпадающих документов, поле total_relation в метаинформации запроса покажет gte, что означает Больше или равно. Это указывает, что фактическое количество совпадений как минимум равно указанному total_found (в SQL) или hits.total (в JSON). Когда количество точное, total_relation будет показывать eq.

Примечание: использование cutoff в агрегатных запросах не рекомендуется, так как это может привести к неточным или неполным результатам.

‹›
  • Example
Example
📋

Использование cutoff в агрегатных запросах может привести к неправильным или вводящим в заблуждение результатам, как показано в следующем примере:

drop table if exists t
--------------
Query OK, 0 rows affected (0.02 sec)
--------------
create table t(a int)
--------------
Query OK, 0 rows affected (0.04 sec)
--------------
insert into t(a) values(1),(2),(3),(1),(2),(3)
--------------
Query OK, 6 rows affected (0.00 sec)
--------------
select avg(a) from t option cutoff=1 facet a
--------------
+----------+
| avg(a)   |
+----------+
| 1.000000 |
+----------+
1 row in set (0.00 sec)
--- 1 out of 1 results in 0ms ---
+------+----------+
| a    | count(*) |
+------+----------+
|    1 |        1 |
+------+----------+
1 row in set (0.00 sec)
--- 1 out of 1 results in 0ms ---

Сравните с тем же запросом без cutoff:

--------------
select avg(a) from t facet a
--------------
+----------+
| avg(a)   |
+----------+
| 2.000000 |
+----------+
1 row in set (0.00 sec)
--- 1 out of 1 results in 0ms ---
+------+----------+
| a    | count(*) |
+------+----------+
|    1 |        2 |
|    2 |        2 |
|    3 |        2 |
+------+----------+
3 rows in set (0.00 sec)
--- 3 out of 3 results in 0ms ---

distinct_precision_threshold

Целое число. По умолчанию 3500. Эта опция задаёт порог, ниже которого подсчёты, возвращаемые count distinct, гарантированно точны в пределах простой таблицы.

Допустимые значения варьируются от 500 до 15500. Значения вне этого диапазона будут ограничены.

Если эта опция установлена в 0, включается алгоритм, обеспечивающий точные подсчёты. Этот алгоритм собирает пары {group, value}, сортирует их и периодически устраняет дубликаты. Результат — точные подсчёты в пределах простой таблицы. Однако этот подход не подходит для наборов данных с высокой кардинальностью из-за высокого потребления памяти и медленного выполнения запросов.

Если distinct_precision_threshold установлен в значение больше 0, Manticore использует другой алгоритм. Он загружает подсчёты в хеш-таблицу и возвращает размер таблицы. Если хеш-таблица становится слишком большой, её содержимое переносится в структуру данных HyperLogLog. В этот момент подсчёты становятся приближенными, так как HyperLogLog — вероятностный алгоритм. Этот подход поддерживает фиксированное максимальное использование памяти на группу, но с компромиссом в точности подсчётов.

Точность HyperLogLog и порог для перехода от хеш-таблицы к HyperLogLog выводятся из настройки distinct_precision_threshold. Важно использовать эту опцию с осторожностью, так как удвоение её значения также удвоит максимальное количество памяти, необходимое для подсчётов. Максимальное использование памяти можно примерно оценить по формуле: 64 * max_matches * distinct_precision_threshold, хотя на практике подсчёты часто используют меньше памяти, чем в худшем случае.

expand_keywords

0 или 1 (по умолчанию 0). Расширяет ключевые слова точными формами и/или звёздочками, когда это возможно. Подробнее см. expand_keywords.

field_weights

Именованный список целых чисел (веса пользователя для ранжирования по полям).

Пример:

SELECT ... OPTION field_weights=(title=10, body=3)

global_idf

Использовать глобальную статистику (частоты) из файла global_idf для вычисления IDF.

idf

Кавычками, через запятую перечисленные флаги вычисления IDF. Известные флаги:

  • normalized: вариант BM25, idf = log((N-n+1)/n), согласно Робертсону и др.
  • plain: простой вариант, idf = log(N/n), согласно Спарку-Джонсу
  • tfidf_normalized: дополнительно делить IDF на количество слов в запросе, чтобы TF*IDF попадал в диапазон [0, 1]
  • tfidf_unnormalized: не делить дополнительно IDF на количество слов в запросе, где N — размер коллекции, а n — количество совпадающих документов

Исторически стандартный IDF (обратная частота документа) в Manticore эквивалентен OPTION idf='normalized,tfidf_normalized', и эти нормализации могут вызывать несколько нежелательных эффектов.

Во-первых, idf=normalized приводит к штрафованию ключевых слов. Например, если вы ищете the | something и the встречается более чем в 50% документов, то документы с обоими ключевыми словами the и something получат меньший вес, чем документы только с ключевым словом something. Использование OPTION idf=plain этого избегает. Простой IDF варьируется в диапазоне [0, log(N)], и ключевые слова никогда не штрафуются; в то время как нормализованный IDF варьируется в диапазоне [-log(N), log(N)], и слишком частые ключевые слова штрафуются.

Во-вторых, idf=tfidf_normalized приводит к дрейфу IDF между запросами. Исторически IDF также делился на количество ключевых слов в запросе, что обеспечивало, что сумма sum(tf*idf) по всем ключевым словам оставалась в диапазоне [0,1]. Однако это означало, что запросы вроде word1 и word1 | nonmatchingword2 присваивали разные веса одному и тому же набору результатов, так как IDF для word1 и nonmatchingword2 делились на 2. Использование OPTION idf='tfidf_unnormalized' решает эту проблему. Учтите, что факторы ранжирования BM25, BM25A, BM25F() будут соответственно скорректированы при отключении этой нормализации.

Флаги IDF могут комбинироваться; plain и normalized взаимоисключающие; tfidf_unnormalized и tfidf_normalized также взаимоисключающие; и неуказанные флаги в таких взаимоисключающих группах по умолчанию принимают свои исходные настройки. Это означает, что OPTION idf=plain эквивалентно полному указанию OPTION idf='plain,tfidf_normalized'.

jieba_mode

Задает режим сегментации Jieba для запроса.

При использовании китайской сегментации Jieba иногда полезно использовать разные режимы сегментации для токенизации документов и запроса. Полный список режимов см. в jieba_mode.

index_weights

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

local_df

0 или 1, автоматически суммирует DF по всем локальным частям распределённой таблицы, обеспечивая согласованный (и точный) IDF для локально шардированной таблицы. По умолчанию включено для дисковых чанков RT-таблицы. Термины запроса с подстановочными знаками игнорируются.

low_priority

0 или 1 (по умолчанию 0). Установка low_priority=1 выполняет запрос с пониженным приоритетом, перепланируя его задачи в 10 раз реже, чем запросы с нормальным приоритетом.

max_matches

Целое число. Максимальное количество совпадений на запрос.

Максимальное количество совпадений, которое сервер хранит в ОЗУ для каждой таблицы и может вернуть клиенту. По умолчанию 1000.

Введено для контроля и ограничения использования ОЗУ, настройка max_matches определяет, сколько совпадений будет храниться в памяти при поиске по каждой таблице. Каждое найденное совпадение всё равно обрабатывается, но в памяти сохраняются только лучшие N из них, которые в итоге возвращаются клиенту. Например, если в таблице для запроса найдено 2 000 000 совпадений, редко нужно получить их все. Вместо этого нужно просканировать все, но выбрать только "лучшие" 500, например, по какому-то критерию (например, по релевантности, цене или другим факторам) и показать эти 500 совпадений пользователю постранично по 20-100 совпадений. Отслеживание только лучших 500 совпадений гораздо эффективнее по памяти и CPU, чем хранение всех 2 000 000, их сортировка и затем отбрасывание всего, кроме первых 20 для страницы результатов. max_matches контролирует N в этом количестве "лучших N".

Этот параметр существенно влияет на использование ОЗУ и CPU на запрос. Значения от 1000 до 10 000 обычно приемлемы, но более высокие лимиты следует использовать с осторожностью. Бездумное увеличение max_matches до 1 000 000 означает, что searchd должен выделить и инициализировать буфер для совпадений на миллион записей для каждого запроса. Это неизбежно увеличит использование ОЗУ на запрос и в некоторых случаях заметно повлияет на производительность.

Дополнительную информацию о влиянии на поведение опции max_matches см. в max_matches_increase_threshold.

max_matches_increase_threshold

Целое число. Устанавливает порог, до которого может быть увеличен max_matches. По умолчанию 16384.

Manticore может увеличить max_matches для повышения точности groupby и/или агрегаций при включённом pseudo_sharding, если обнаружит, что количество уникальных значений атрибута groupby меньше этого порога. Потеря точности может возникать, когда pseudo-sharding выполняет запрос в нескольких потоках или когда RT-таблица проводит параллельные поиски в дисковых чанках.

Если количество уникальных значений атрибута groupby меньше порога, max_matches будет установлено в это число. В противном случае будет использоваться значение max_matches по умолчанию.

Если max_matches было явно задано в опциях запроса, этот порог не действует.

Учтите, что слишком высокий порог приведёт к увеличенному потреблению памяти и общему снижению производительности.

Вы также можете включить режим гарантированной точности groupby/aggregate с помощью опции accurate_aggregation.

max_query_time

Устанавливает максимальное время выполнения поискового запроса в миллисекундах. Должно быть неотрицательным целым числом. Значение по умолчанию — 0, что означает «не ограничивать». Локальные поисковые запросы будут остановлены после истечения указанного времени. Обратите внимание, что если вы выполняете поиск, который обращается к нескольким локальным таблицам, это ограничение применяется к каждой таблице отдельно. Имейте в виду, что это может немного увеличить время отклика запроса из-за накладных расходов, связанных с постоянным отслеживанием времени остановки запроса.

max_predicted_time

Целое число. Максимальное предсказанное время поиска; см. predicted_time_costs.

morphology

none позволяет заменять все термины запроса их точными формами, если таблица была построена с включённым index_exact_words. Это полезно для предотвращения стемминга или лемматизации терминов запроса.

not_terms_only_allowed

0 или 1 разрешает использование отдельного отрицания в запросе. Значение по умолчанию — 0. См. также соответствующую глобальную настройку.

‹›
  • SQL
SQL
📋
MySQL [(none)]> select * from tbl where match('-donald');
ERROR 1064 (42000): index t: query error: query is non-computable (single NOT operator)
MySQL [(none)]> select * from t where match('-donald') option not_terms_only_allowed=1;
+---------------------+-----------+
| id                  | field     |
+---------------------+-----------+
| 1658178727135150081 | smth else |
+---------------------+-----------+

ranker

Выберите из следующих вариантов:

  • proximity_bm25
  • bm25
  • none
  • wordcount
  • proximity
  • matchany
  • fieldmask
  • sph04
  • expr
  • export

Для получения подробной информации о каждом ранжировщике смотрите Ранжирование результатов поиска.

rand_seed

Позволяет указать конкретное целочисленное значение зерна для запроса ORDER BY RAND(), например: ... OPTION rand_seed=1234. По умолчанию для каждого запроса автоматически генерируется новое и уникальное значение зерна.

retry_count

Целое число. Количество повторных попыток в распределённом режиме.

retry_delay

Целое число. Задержка между повторными попытками в распределённом режиме, в миллисекундах.

scroll

Строка. Токен прокрутки для постраничного вывода результатов с использованием подхода Scroll pagination.

sort_method

  • pq — очередь с приоритетом, установлена по умолчанию
  • kbuffer — обеспечивает более быструю сортировку для уже предварительно отсортированных данных, например, данных таблицы, отсортированных по id Набор результатов одинаков в обоих случаях; выбор одного из вариантов может просто улучшить (или ухудшить) производительность.

threads

Ограничивает максимальное количество потоков, используемых для обработки текущего запроса. По умолчанию — без ограничений (запрос может использовать все потоки, определённые глобально). Для пакета запросов опция должна быть добавлена к самому первому запросу в пакете, после чего применяется при создании рабочей очереди и действует для всего пакета. Эта опция имеет то же значение, что и опция max_threads_per_query, но применяется только к текущему запросу или пакету запросов.

token_filter

Заключённая в кавычки строка с разделением двоеточиями в формате название библиотеки:название плагина:необязательная строка настроек. Для каждого поиска при вызове полнотекстового поиска каждой задействованной таблицей создаётся фильтр токенов во время выполнения запроса, что позволяет реализовать пользовательский токенизатор, генерирующий токены согласно пользовательским правилам.

SELECT * FROM index WHERE MATCH ('yes@no') OPTION token_filter='mylib.so:blend:@'

expansion_limit

Ограничивает максимальное количество расширенных ключевых слов для одного подстановочного знака, значение по умолчанию 0 означает отсутствие ограничения. Для дополнительной информации смотрите expansion_limit.

Подсказки оптимизатора запросов

В редких случаях встроенный анализатор запросов Manticore может неправильно понять запрос и определить, следует ли использовать индекс docid, вторичные индексы или колонковое сканирование. Чтобы переопределить решения оптимизатора запросов, вы можете использовать следующие подсказки в вашем запросе:

  • /*+ DocidIndex(id) */ — принудительно использовать индекс docid, /*+ NO_DocidIndex(id) */ — указать оптимизатору игнорировать его
  • /*+ SecondaryIndex(<attr_name1>[, <attr_nameN>]) */ — принудительно использовать вторичный индекс (если доступен), /*+ NO_SecondaryIndex(id) */ — указать оптимизатору игнорировать его
  • /*+ ColumnarScan(<attr_name1>[, <attr_nameN>]) */ — принудительно использовать колонковое сканирование (если атрибут колонковый), /*+ NO_ColumnarScan(id) */ — указать оптимизатору игнорировать его

Обратите внимание, что при выполнении полнотекстового запроса с фильтрами оптимизатор запросов выбирает между пересечением результатов полнотекстового дерева с результатами фильтра или использованием стандартного подхода match-then-filter. Указание любой подсказки заставит демон использовать путь кода, который выполняет пересечение результатов полнотекстового дерева с результатами фильтра.

Для получения дополнительной информации о работе оптимизатора запросов смотрите страницу Оптимизатор на основе стоимости.

‹›
  • SQL
SQL
📋
SELECT * FROM students where age > 21 /*+ SecondaryIndex(age) */

При использовании клиента MySQL/MariaDB убедитесь, что включён флаг --comments для активации подсказок в ваших запросах.

‹›
  • mysql
mysql
📋
mysql -P9306 -h0 --comments
Last modified: August 28, 2025