为什么语音搜索比普通匹配查询慢得多

Why is a phonetic search so much slower than a normal match query

总结:我试图理解为什么两个在复杂度上看起来非常相似的查询在执行速度上却大不相同。

我正在使用 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)",

在一个拥有约 1500 万条记录的索引上执行此操作大约需要 200 毫秒。

因为它似乎将我的单个搜索词转换为 5 个同义词,所以我认为 "well, what if i search for the same 5 terms without phonetic? Will it be similarily slow?" 或者换句话说 "is it not the phonetic part that makes it slow, but the fact that it has to search for several synonyms?"

但事实证明,如果我查询 "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 的人来说,这两个查询在复杂性上看起来非常相似(使用 OR 运算符搜索 5 个术语),我不明白为什么一个比其他.

任何见解将不胜感激!

提前致谢!

问候 马里奥

P.S.: 我意识到如果我包括我在这个例子中使用的两个查询可能会有所帮助:

第一次查询(拼音):

{
  "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
    }
  }
}

我想说这两者之间的区别非常清楚 - rewrite 过程也就是将术语 mario 扩展为存在的同义词。这个过程基本上需要您通过 SynonymGraphFilter 进行处理,我相信它会从磁盘读取有关同义词的数据,这会使速度变慢。

在布尔查询的情况下,匹配通过不同的分析器链(我相信这只是一个拼音,但没有同义词)