扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
这期内容当中小编将会给大家带来有关如何分析Elasticsearch中奇怪的查询命中数问题,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。
创新互联是一家集网站建设,宣恩企业网站建设,宣恩品牌网站建设,网站定制,宣恩网站建设报价,网络营销,网络优化,宣恩网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。
业务部门反馈,在某个月份的索引中,当查询条件不变,仅添加一个索引前缀到请求中后,搜索返回的命中数量反而降低,如下图所示,从索引 skylay*_alarm-2020.02* 中查询时,命中结果总数 total为49条

但是当添加了一个索引前缀 skylar*_alarm-2020.01* ,从 skylay*_alarm-2020.02*,skylar*_alarm-2020.01* 两组索引一起查询时,命中结果总数居然降低为15条了:

按照常规理解,添加一个索引到查询条件中,命中结果集只可能更多,不应该降低,仔细观察返回结果,发现 _shards 中的 skipped 非常多,这点很可疑,感觉多半与他有关。
分析查询问题,首先想到的就是 profile 一把,在请求体中添加 "profile": true, 可惜没看到有价值的东西,然后 google 一把,看有没有其他人遇到 skipped 问题,发现在社区中很多人问到 skipped相关问题,基本没有人回复,唯一有价值的答复如下:
Are shards skipped when a range query does not create hits
Yes, there is a pre-flight search phase called the can match search phase that removes all shards from a search request that a query can not match (e.g., if a range query does not overlap with the range of values for a shard). This feature exists since 5.6.
这段内容大致是说从5.6版本开始,在真正的查询开始之前根据某些条件跳过不会匹配到的分片,例如范围查询过程中,某些分片的值不在查询区间。
除此之外再无更多内容,只能从源码层面继续分析。函数AbstractSearchAsyncAction#buildSearchResponse 负责构建查询返回结果,skipped数量取决于这个类中的一个计数器,继续向上翻,找到将分片标记为 skip 的地方CanMatchPreFilterSearchPhase#getIterator:
private GroupShardsIterator getIterator(...) {
for (SearchShardIterator iter : shardsIts) {
if (possibleMatches.get(i++)) {
iter.reset();
} else {
//标记为 skip,查询的时候不会去查
iter.resetAndSkip();
}
}
return shardsIts;
}
由于需要优先解决线上问题,暂时先不分析分片被设置为 skip 都会有哪些条件,CanMatchPreFilterSearchPhase这个阶段只有满足一定条件时才会执行,也就是说如果不走这个阶段就不会去检查分片要不要被 skip。检查条件在 TransportSearchAction#shouldPreFilterSearchShards中实现,在此不再贴代码,总结起来常见条件包括下面几个,满足下列条件之一时,不走 CanMatchPreFilterSearchPhase (暂且称为“预过滤”)流程。
查询中带有 Global Aggregation
查询中带有聚合,并且聚合中设置了:"min_doc_count": 0
待查询的分片数小于 128,由查询参数 pre_filter_shard_size指定。
查询中使用了 Suggester
找到了可以跳过“预过滤”的条件,问题解决问题就比较简单,有两种方式不影响现有业务:
对于含有聚合请求的查询,可以在聚合请求中添加 "min_doc_count": 0
对于不含聚合请求的查询,可以在请求中调整pre_filter_shard_size参数,让他大于待查询的分片数,
例如:_search?pre_filter_shard_size=1000
当然,也可以统一使用 pre_filter_shard_size 参数。到此问题解决了,skipped 分片消失:
上述就是小编为大家分享的如何分析Elasticsearch中奇怪的查询命中数问题了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注创新互联行业资讯频道。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流