ES搜索性能优化

在项目中有用到Elastic Search来进行数据的索引和搜索工作。在一开始接手的时候,搜索接口的耗时在六七百毫秒,相对一般的接口来说是一个比较耗时的操作了。

在后期的优化和学习过程中,对ES的特性和原理进行初步的了解,并对ES的搜索性能进行了优化,将搜索接口的耗时降低到了平均150ms左右,性能提高了将近5倍。

虽然是个很小的改动,但效果确实显著,记录一下中间具体的过程。

初始ES搜索的概况

在一开始的ES搜索中,其实也是一个比较简单的过滤条件。隐藏一些业务细节,最抽象的版本可以概括为

{
  "query": { 
    "function_score": {
      "query": {
        "bool": { 
          "filter": [ 
            {
              "terms": {
                "status": [1,2]
              }
            },
            .....
          ]
        }
        .....
      },
      "functions": [
        .....
      ], 
      "score_mode": "sum",
      "boost_mode": "sum"
    }
  },
  "from": 0,
  "size": 20
}

在用kibina自带的非常方便的工具来分析具体的搜索过程耗时时,发现最主要的时间花在了build_scorer的过程中。如果把build_scorer的耗时减少,能够大幅的加快接口的处理速度。

在不断的试验过程中,发现如果将status的过滤条件删除,耗时大为减少,所以目标确定为找到status的过滤条件耗时长的原因。

经过各方面的资料查找,发现网上的很多建议并不靠谱,或者说并不适合我们所面临的状态。不过幸好,最终发现了这篇文章: https://www.jianshu.com/p/e9be6740b724 , 一下子解决了我们的问题。这篇文章对优化的原理讲的很明白了, 这边只是个人再记录一下。

ES优化建议

直接说结论: 对于数值类型,需要在构建索引的时候就明确这个字段是否需要进行范围查询RangeQuery,还是只需要做精确的TermQuery;如果类似我们的这种status字段,只需要进行精确的TermQuery,或者查询少数的几种数值情况,在构建索引的时候,需要预先指定对应的字段为keyword类型,而不要使用ES默认的数值类型short。

ES优化原理

再记录一下上述优化建议的原理。

  1. 在ES5.x之前用到的Lucene版本,即使是被定义成数值类型,最终其实还是按照文本类型对其进行了倒排索引。

    所以针对上边我们的情况,如果在ES5.x之前的版本,status字段即使是存成了默认的数值字段,还是会在底层建立倒排索引,上边的搜索条件其实也是会非常快的。

  2. 这种处理方式虽然对这种TermQuery的搜索比较快速,但是如果要用到RangeQuery,就有点力不从心了。 对于RangeQuery,比如status range from 0 to 100,这种情况就需要查询 status 从0到100的倒排索引,尤其在RangeQuery的范围比较大的时候,性能缺陷更为明显。

  3. 为了加快RangeQuery,ES5.x用到的Lucene对数值类型进行了优化,将其从倒排索引转成了Block k-d tree的数据结构。Block k-d tree可以简单的理解成为一个二叉树的结构,一方面采用了这种类似二叉树的结构,另一方面ES针对RangeQuery进行了一系列的优化,加快了RangeQuery的搜索效率。

  4. 正是由于ES5.x针对数值类型进行了这方面的优化,虽然对于RangeQuery更有效率,但是对于TermQuery的情况,由于没有了倒排索引,所以在进行TermQuery的时候,需要先根据符合条件的docid构建出一个巨大的bitset出来。所以增加了耗时。

所以结论就是,如果要进行TermQuery,索引的类型适合定义成keyword类型,以利用它的倒排索引结构; ES的默认的数值类型更适合进行RangeQuery的查询。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值