反例:使用 bucket_sort 深分页 RT 达到 5000ms+
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();boolQuery.filter(QueryBuilders.termQuery(EsNewApplyDocumentFields.IS_DEL, 0));TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("spuIdAgg").field("spuId").order(BucketOrder.key(false)).size(pageNum*pageSize);termsAggregationBuilder.subAggregation(new BucketSortPipelineAggregationBuilder("spuBucket",null).from((pageNum-1)*pageSize).size(pageSize));searchSourceBuilder.query(boolQuery).aggregation(termsAggregationBuilder).size(0);
正例:使用 Composite Aggregation 优化后深分页查询:423ms
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();boolQuery.filter(QueryBuilders.termQuery(EsNewApplyDocumentFields.IS_DEL, 0));CompositeAggregationBuilder compositeBuilder = new CompositeAggregationBuilder("spuIdAgg",Collections.singletonList(new TermsValuesSourceBuilder("spuId").field("spuId").order("desc"))).aggregateAfter(ImmutableMap.of("spuId", "603030")).size(20);searchSourceBuilder.query(boolQuery).aggregation(compositeBuilder).aggregation(totalAgg).size(0);
分页10. 避免使用 from+size 方式 。ES 中深度翻页排序的花费会随着分页的深度而成倍增长,分页搜索不会单独“Cache” 。每次分页的请求都是一次重新搜索的过程,而不是从第一次搜索的结果中获取 。如果数据特别大对 CPU 和内存的消耗会非常巨大甚至会导致 OOM 。
11. 避免高实时性&大结果集场景使用 Scroll 方式 。基于快照的上下文 。实时性高的业务场景不建议使用 。大结果集场景将生成大量Scroll 上下文 , 可能导致内存消耗过大,建议使用 SearcheAfter 方式 。
思考:对于 Scroll 和 SearchAfter 的选用怎么看?两者分别适用于哪种场景?SearchAfter 可以完全替代 Scroll 吗?
Scroll 维护一份当前索引段的快照,适用于非实时滚动遍历全量数据查询,但大量Contexts 占用堆内存的代价较高;7.10 引入的新特性 Search After + PIT,查询本质是利用前向页面的一组排序之检索匹配下一页,从而保证数据一致性;8.10 官方文档明确指出不再建议使用 Scroll API 进行深分页 。如果分页检索超过 Top10000+ 推荐使用 PIT + Search After 。
12. SearchAfter 分页/Scroll ID/ 遍历索引中的数据指定 Sort 字段要保证唯一性 , 否则会造成分页/遍历数据不完整或重复 。13. 建议指定业务字段排序 , 不要采用默认打分排序 。ES 默认使用“_score”字段按评分排序 。如在使用 Scroll API 获取数据时,如果没有特殊的排序需求 , 推荐使用"sort":"_doc"让 ES 按索引顺序返回命中文档,可以节省排序开销 。原因如下:
- 使用非文档 ID 排序,会导致每次查询 ES 需要在每个分片记住上次返回的最后一个文档 , 然后下次查询中会对之前已经返回的文档进行忽略过滤,同时在协调节点进行排序操作 。文档 ID 排序则不需要上述操作 。
- 对于文档 ID 排序,ES 内部进行了特殊优化,性能表现更优 。
其他15. 注意 Must 和 Should 同时出现在语句里的时候 , Should 会失效;注意 Must 和 Should 同时出现在同一层级的 bool 查询时,Should 查询会失效 。正例:
{"query":{ "bool":{"must":[{"bool":{"must":[{"term":{"status.keyword":"1"} }]}},{"bool":{"should":[{"term":{"tag.keyword":"1"} } ] }}]}}}
反例:{"query":{"bool":{"must":[{"term":{"status.keyword":"1"}}],"should":[{"term":{"tag.keyword":"1"}}]}}}
16. 避免查询 indexName-* 。
因为 Elasticsearch 中的索引名称是全局可见的,可以通过查询所有索引的方式来枚举某个集群中的所有索引名称 。可以通过在 Elasticsearch 配置文件中设置 action.destructive_requires_name 参数来禁止查询 indexName-* 。17. 脚本使用 Stored 方式,避免使用 Inline 方式 。对于固定结构的 Script,使用 Stored 方式,把脚本通过 Kibana 存入 ES 集群 , 降低重复编译脚本带来的性能损耗 。
推荐阅读
- 手机卡顿反应慢,原来是这个设置没关,关掉它,手机立马流畅不卡
- 朋友圈个性签名能怎么改,微信个性签名怎么在更多里面
- 删除短信怎么找回,一个手机号的短信怎么恢复
- 生儿不如养儿!20年前金星领养的三个孩子,如今怎样了!
- 湖北小伙被外国美女模特倒追,生下两个混血女儿,大女儿超像杨幂
- 个人去税务局开票需要提供什么
- 小米手环5如何储存多个表盘,小米手环5如何设置太空人壁纸
- 疯马秀风波四个月:张嘉倪baby遭封杀,人气跌落神色憔悴。
- 周海媚离开令马景涛肝肠寸断,咆哮帝一个用生命演戏的男人
- 有一种“整容”叫唐艺昕结婚,老公张若昀变化不大,她却像换了个人