问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

ES模糊查询性能优化:match_phrase与nGram的最佳实践

创作时间:
作者:
@小白创作中心

ES模糊查询性能优化:match_phrase与nGram的最佳实践

引用
CSDN
10
来源
1.
https://blog.csdn.net/qq1261275789/article/details/142063622
2.
https://m.blog.csdn.net/qq_33240556/article/details/137136586
3.
https://discuss.elastic.co/t/improve-search-performance/359306
4.
https://www.pipiho.com/es/7.7/cn/query-dsl-wildcard-query.html
5.
https://vimsky.com/examples/detail/python-ex-pyelasticsearch-ElasticSearch-optimize-method.html
6.
https://discuss.elastic.co/t/want-to-do-partial-match-without-using-wildcards/362928
7.
https://openobserve.ai/resources/elasticsearch-matching
8.
https://www.alibabacloud.com/blog/optimizing-high-cpu-usage-for-elasticsearch-on-alibaba-cloud_601213
9.
https://developer.volcengine.com/articles/7322138664606105626
10.
https://www.cnblogs.com/yucongblog/p/18594186

在Elasticsearch中,模糊查询是常见的搜索需求,但传统的wildcard查询往往存在性能瓶颈。本文将分享一种更优的解决方案:使用match_phrase查询结合nGram分词器,既能满足模糊匹配需求,又不会影响系统性能。

ES模糊查询的挑战

在实际应用中,用户经常需要进行模糊搜索,比如搜索商品名称、地址等字段时,希望即使输入不完全也能找到匹配结果。然而,传统的模糊查询方式存在以下问题:

  1. 性能瓶颈:wildcard查询在数据量较大时性能急剧下降,特别是当模式以通配符开头时,需要扫描大量词条。

  2. 资源消耗:模糊查询会占用较多的CPU和内存资源,影响整个系统的响应速度。

  3. 准确性问题:传统的模糊匹配可能产生大量无关结果,影响用户体验。

wildcard查询的局限性

wildcard查询虽然灵活,但存在以下局限:

  • 性能问题:当模式以*或?开头时,需要扫描大量词条,导致性能下降。
  • 资源消耗:这类查询可能非常耗资源,特别是在大规模数据集上。
  • 配置限制:需要通过search.allow_expensive_queries设置来控制是否允许执行,否则可能影响集群稳定性。

优化方案:match_phrase + nGram

为了解决上述问题,我们可以采用match_phrase查询结合nGram分词器的方式。这种方法既能实现模糊匹配,又能保持较高的查询性能。

nGram分词器原理

nGram分词器会将文本拆分成连续的n个字符的子串。例如,对于单词"elasticsearch",使用nGram分词器(min_gram=3, max_gram=3)会得到以下结果:

ela
las
ast
stc
tc

通过这种方式,即使用户输入不完整的关键词,也能匹配到相关结果。

配置示例

首先,我们需要在ES中配置nGram分词器:

PUT /my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "ngram_analyzer": {
          "tokenizer": "ngram_tokenizer"
        }
      },
      "tokenizer": {
        "ngram_tokenizer": {
          "type": "ngram",
          "min_gram": 3,
          "max_gram": 3,
          "token_chars": [
            "letter",
            "digit"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "ngram_analyzer",
        "search_analyzer": "standard"
      }
    }
  }
}

然后,我们可以使用match_phrase查询来实现模糊搜索:

GET /my_index/_search
{
  "query": {
    "match_phrase": {
      "title": "elastic"
    }
  }
}

最佳实践

  1. 合理设置nGram参数:min_gram和max_gram的值不宜过大,否则会增加索引大小。通常3-4个字符是一个较好的选择。

  2. 区分索引和查询分析器:使用不同的分析器进行索引和查询,索引时使用nGram,查询时使用标准分析器,可以提高匹配精度。

  3. 控制查询复杂度:通过search.allow_expensive_queries设置来限制昂贵的查询,保护集群稳定性。

  4. 定期优化索引:使用ES的optimize方法定期合并段,减少资源消耗。例如:

from pyelasticsearch import ElasticSearch

client = ElasticSearch('http://0.0.0.0:9200/')
client.optimize('time_*', max_num_segments=1, wait_for_merge=True)

通过上述方法,我们可以在Elasticsearch中实现高效、精准的模糊搜索,同时保持良好的系统性能。这种方案特别适用于电商、地址搜索等需要灵活模糊匹配的场景。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号