温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何分析Elasticsearch中奇怪的查询命中数问题

发布时间:2021-12-10 11:33:41 来源:亿速云 阅读:618 作者:柒染 栏目:大数据

这期内容当中小编将会给大家带来有关如何分析Elasticsearch中奇怪的查询命中数问题,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

业务部门反馈,在某个月份的索引中,当查询条件不变,仅添加一个索引前缀到请求中后,搜索返回的命中数量反而降低,如下图所示,从索引 skylay*_alarm-2020.02* 中查询时,命中结果总数 total为49条

如何分析Elasticsearch中奇怪的查询命中数问题

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

如何分析Elasticsearch中奇怪的查询命中数问题


按照常规理解,添加一个索引到查询条件中,命中结果集只可能更多,不应该降低,仔细观察返回结果,发现 _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<SearchShardIterator> 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中奇怪的查询命中数问题

在 ES 使用过程中需要看代码才能解决问题的时候比较少,但是关于查询过程中分片 skipped 的原理在官方文档中没有具体说明,甚至在手册中没有解释这个字段的含义。这次业务方使用的 ES 版本为5.6.12,不确定新版本的 ES 是否也存在类似问题,未来抽时间在新版本上分析一下“预过滤”的原理。

上述就是小编为大家分享的如何分析Elasticsearch中奇怪的查询命中数问题了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI