elasticsearch中的常见问题和优化策略

参考:https://www.phpmianshi.com/?id=216

常见优化策略:

filter过滤器查询优化

结果分数是Elasticsearch的关键。 通常,当您使用搜索引擎时,您需要最准确的结果。 例如,如果您正在搜索“苹果”,您不希望结果包括“苹果手机”。

Elasticsearch根据您提供的参数对查询结果进行评分。

虽然查询相关性不是本篇文章的重点,但重要的是在此提及,因为如果您有快速搜索需求但结果不是您要查找的结果,则整个搜索都是浪费时间。 那么,你如何加快搜索速度?

1 查询时,使用query-bool-filter组合取代普通query

提高搜索性能的一种方法是使用过滤器。 过滤后的查询可能是您最需要的。

首先过滤是很重要的,因为搜索中的过滤器不会影响文档分数的结果,因此您在资源方面使用很少的资源来将搜索结果范围缩小到很小。

使用过滤查询,结合使用布尔匹配,您可以在评分之前搜索包含X的所有文档,或者不包含Y的所有文档。此外,可以filter是可以被缓存的。

 

2 避免使用script查询

避免使用脚本查询来计算匹配。 推荐:建立索引时存储计算字段。

例如,我们有一个包含大量用户信息的索引,我们需要查询编号以“1234”开头的所有用户。 您可能希望运行类似“source”的脚本查询: doc ['num'].value.startsWith('1234') 此查询非常耗费资源并且会降低整个系统的速度。  合理的建议:考虑在索引时添加名为“num_prefix”的字段。 然后我们可以查询 “name_prefix”:“1234”。

3 避免使用wildcard查询

主要原因:wildcard类似mysql中的like,和分词完全没有了关系。

出现错误:用户输入的字符串长度没有做限制,导致首尾通配符中间可能是很长的一个字符串。 后果就是对应的wildcard Query执行非常慢,非常消耗CPU。

根本原因:为了加速通配符和正则表达式的匹配速度,Lucene4.0开始会将输入的字符串模式构建成一个DFA (Deterministic Finite Automaton),带有通配符的pattern构造出来的DFA可能会很复杂,开销很大。

可能的优化方案:

  1. wildcard query应杜绝使用通配符打头,实在不得已要这么做,就一定需要限制用户输入的字符串长度。

  2. 最好换一种实现方式,通过在index time做文章,选用合适的分词器,比如nGram tokenizer预处理数据,然后使用更廉价的term query来实现同等的模糊搜索功能。

  3. 对于部分输入即提示的应用场景,可以考虑优先使用completion suggester, phrase/term/suggeter一类性能更好,模糊程度略差的方式查询,待suggester没有匹配结果的时候,再fall back到更模糊但性能较差的wildcard, regex, fuzzy一类的查询。

详尽原理参考:https://elasticsearch.cn/article/171

4 合理使用keyword类型

ES5.x里对数值型字段做TermQuery可能会很慢。

在ES5.x+里,一定要注意数值类型是否需要做范围查询,看似数值,但其实只用于Term或者Terms这类精确匹配的,应该定义为keyword类型。

典型的例子就是索引web日志时常见的HTTP Status code。

详尽原理参考:https://elasticsearch.cn/article/446

5 控制字段的返回

一是:数据建模规划的时候,在Mapping节点对于仅存储、是否构建倒排索引通过enabled、index参数进行优化。

二是:_source控制返回,不必要的字段不需要返回,举例:采集的原文章详情内容页,根据需要决定是否返回。

6 空值的处理

如果同步的内容有可能有空值尽量设置一个默认值

6.1 比如:state状态为空为正常状态,则可以设置一个默认none,查询正常状态就可以term=none  查询不为空可以把所有可能的情况都列出来用terms

SELECT (CASE state WHEN '' THEN 'none' ELSE state END) as es_state from table

 

6.2 当然最好还是用 keyword分析器来查询, 比如 filed.keyword="" 这样也是能正常查询出来的

常见问题和解决方案

1.text类型需要排序

报错如下:

Fielddata is disabled on text fields by default. Set fielddata=true on [gender] in order to load fielddata in memory by uninverting the inverted index

场景:

定义了is_hot 是否热门,为了让它支持精确查询,定义成了text类型,但是还需要先根据是否热门排序,再根据热度排序

 

问题原因:

根据官方文档显示,出现该错误是因为5.x之后,Elasticsearch对排序、聚合所依据的字段用单独的数据结构(fielddata)缓存到内存里了,但是在text字段上默认是禁用的,如果有需要单独开启,这样做的目的是为了节省内存空间。

官方文档地址:https://www.elastic.co/guide/en/elasticsearch/reference/current/fielddata.html

开启方法:

curl -XPUT 'http://localhost:9200/my_index/_mapping' -d '
{
  "properties": {
        "is_hot": {
            "type": "text",
            "fielddata": true
        }
    }
}'

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值