Почему фонетический поиск намного медленнее, чем обычный запрос на совпадение
Резюме: я пытаюсь понять, почему два запроса, которые кажутся очень похожими по сложности, сильно отличаются по скорости выполнения.
Я использую Elastic Search 6.4, и у меня есть поле имени, для которого я хотел бы использовать фонетические запросы.
В качестве примера я профилировал фонетический запрос для поискового термина "Mario" и обнаружил, что Lucene в фоновом режиме выполняет это как SynonymQuery:
"type": "SynonymQuery",
"description": "Synonym(person.firstName.phonetic:mYrio person.firstName.phonetic:mari person.firstName.phonetic:mario person.firstName.phonetic:mori person.firstName.phonetic:morio)",
и это занимает около 200 мсек для индекса с ~15 миллионами записей.
Так как он, казалось, преобразовал мой единственный поисковый термин в 5 синонимов, я подумал: "Ну что, если я буду искать те же 5 терминов без фонетики? Будет ли это так же медленно?" или другими словами "не фонетическая часть делает его медленным, а тот факт, что он должен искать несколько синонимов?"
Но оказывается, что если я сделаю запрос к полю без фонетического слова "mario mYrio mari mori morio", то получится BooleanQuery (с одним запросом на один синоним для детей):
"type": "BooleanQuery",
"description": "person.firstName:mario person.firstName:mYrio person.firstName:mari person.firstName:mori person.firstName:morio",
это занимает только 1/10 времени. Обратите внимание: я знаю и понимаю, что эти два запроса дают разные результаты. Я не пытаюсь симулировать фонетический поиск со вторым запросом. я просто хотел посмотреть, будет ли это так же медленно, потому что это был запрос с аналогичной сложностью.
для кого-то вроде меня, который только недавно начал использовать Elastic Search, эти два запроса выглядят очень похожими по сложности (поиск по 5 терминам с оператором OR), и я не могу понять, почему один намного медленнее, чем другой.
Любое понимание будет высоко ценится!
Заранее спасибо!
С уважением Марио
PS: я понял, что это, вероятно, поможет, если я включу два запроса, которые я использовал в этом примере:
первый запрос (фонетический):
{
"profile": true,
"size": 1,
"timeout": "10s",
"query": {
"bool": {
"should": [
{
"match": {
"person.firstName.phonetic": {
"query": "mario",
"operator": "OR",
"prefix_length": 0,
"max_expansions": 50,
"fuzzy_transpositions": true,
"lenient": false,
"zero_terms_query": "NONE",
"auto_generate_synonyms_phrase_query": true,
"boost": 1
}
}
}
],
"adjust_pure_negative": true,
"boost": 1
}
}
}
второй запрос (не фонетический):
{
"profile": true,
"size": 1,
"timeout": "10s",
"query": {
"bool": {
"should": [
{
"match": {
"person.firstName": {
"query": "mario myrio mari mori morio",
"operator": "OR",
"fuzziness": "0",
"prefix_length": 3,
"max_expansions": 50,
"fuzzy_transpositions": true,
"lenient": false,
"zero_terms_query": "NONE",
"auto_generate_synonyms_phrase_query": true,
"boost": 1
}
}
}
],
"adjust_pure_negative": true,
"boost": 1
}
}
}
1 ответ
Я бы сказал, что довольно ясно, в чем разница между этими двумя - rewrite
процесс ака расширение срока mario
к синонимам, которые существуют. Этот процесс в основном требует от вас обработки через SynonymGraphFilter, который, я считаю, считывает данные о синонимах с диска, что замедляет работу.
В случае логического запроса совпадение проходит через другую цепочку анализатора (что, я думаю, является фонетическим, но без синонимов)