Elasticsearch 性能优化详解( 三 )


修改 translog 相关的设置一是控制数据从内存到硬盘的操作频率,以减少硬盘 IO 。可将 sync_interval 的时间设置大一些 。默认为5s 。
index.translog.sync_interval: 5s也可以控制 tranlog 数据块的大小,达到 threshold 大小时,才会 flush 到 lucene 索引文件 。默认为512m 。
index.translog.flush_threshold_size: 512mbtranslog我们在[原理:ES原理之索引文档流程详解]也有介绍 。
注意 _id 字段的使用_id 字段的使用,应尽可能避免自定义 _id , 以避免针对 ID 的版本管理;建议使用 ES 的默认 ID 生成策略或使用数字类型 ID 做为主键 。
注意 _all 字段及 _source 字段的使用_all 字段及 _source 字段的使用,应该注意场景和需要 , _all 字段包含了所有的索引字段,方便做全文检索 , 如果无此需求,可以禁用;_source 存储了原始的 document 内容,如果没有获取原始文档数据的需求,可通过设置 includes、excludes 属性来定义放入 _source 的字段 。
合理的配置使用 index 属性合理的配置使用 index 属性,analyzed 和 not_analyzed , 根据业务需求来控制字段是否分词或不分词 。只有 groupby 需求的字段,配置时就设置成 not_analyzed , 以提高查询或聚类的效率 。
减少副本数量Elasticsearch 默认副本数量为3个,虽然这样会提高集群的可用性,增加搜索的并发数,但是同时也会影响写入索引的效率 。
在索引过程中,需要把更新的文档发到副本节点上,等副本节点生效后在进行返回结束 。使用 Elasticsearch 做业务搜索的时候,建议副本数目还是设置为3个,但是像内部 ELK 日志系统、分布式跟踪系统中,完全可以将副本数目设置为1个 。
查询方面优化Elasticsearch 作为业务搜索的近实时查询时,查询效率的优化显得尤为重要 。
路由优化当我们查询文档的时候 , Elasticsearch 如何知道一个文档应该存放到哪个分片中呢?它其实是通过下面这个公式来计算出来的 。
shard = hash(routing) % number_of_primary_shardsrouting 默认值是文档的 id,也可以采用自定义值,比如用户 ID 。
不带 routing 查询在查询的时候因为不知道要查询的数据具体在哪个分片上,所以整个过程分为2个步骤:

  • 分发:请求到达协调节点后 , 协调节点将查询请求分发到每个分片上 。
  • 聚合:协调节点搜集到每个分片上查询结果,再将查询的结果进行排序,之后给用户返回结果 。
带 routing 查询查询的时候,可以直接根据 routing 信息定位到某个分配查询 , 不需要查询所有的分配,经过协调节点排序 。
向上面自定义的用户查询,如果 routing 设置为 userid 的话,就可以直接查询出数据来 , 效率提升很多 。
Filter VS Query尽可能使用过滤器上下文(Filter)替代查询上下文(Query)
  • Query:此文档与此查询子句的匹配程度如何?
  • Filter:此文档和查询子句匹配吗?
Elasticsearch 针对 Filter 查询只需要回答「是」或者「否」,不需要像 Query 查询一样计算相关性分数,同时Filter结果可以缓存 。
深度翻页在使用 Elasticsearch 过程中,应尽量避免大翻页的出现 。
正常翻页查询都是从 from 开始 size 条数据 , 这样就需要在每个分片中查询打分排名在前面的 from+size 条数据 。协同节点收集每个分配的前 from+size 条数据 。协同节点一共会受到 N*(from+size) 条数据,然后进行排序 , 再将其中 from 到 from+size 条数据返回出去 。如果 from 或者 size 很大的话,导致参加排序的数量会同步扩大很多,最终会导致 CPU 资源消耗增大 。
可以通过使用 Elasticsearch scroll 和 scroll-scan 高效滚动的方式来解决这样的问题 。
也可以结合实际业务特点 , 文档 id 大小如果和文档创建时间是一致有序的,可以以文档 id 作为分页的偏移量,并将其作为分页查询的一个条件 。
脚本(script)合理使用我们知道脚本使用主要有 3 种形式 , 内联动态编译方式、_script 索引库中存储和文件脚本存储的形式;一般脚本的使用场景是粗排,尽量用第二种方式先将脚本存储在 _script 索引库中,起到提前编译,然后通过引用脚本 id,并结合 params 参数使用,即可以达到模型(逻辑)和数据进行了分离,同时又便于脚本模块的扩展与维护 。


推荐阅读