ElasticSearch QueryCache漫谈

2021-12-28 00:00:00 索引 缓存 简单 则是 判定

前言

这些天在做ES调优,因为之前更多的是考虑ES的架构和可运维性,并没有过多关注query调优这块。今天一查Query Cache相关的内容,发现是少之又少。于是自己深入Dig了下,总算是有所了解。

Query Cache是什么

首先 ES Query Cache是实例级别的,作用域是Node实例。其次,ES Query Cache 本质是缓存Query里面的子Query的查询结果。他是按照子Query来确定是否被Cache。 Cache的结果是DocIdSet,可以简单理解为布隆过滤器。

如何判定一个子Query是否会被Cache住

ES已经比较智能,你可以写一个非常复杂的Query,但是他会自动挑选里面某一部分进行Cache.那么我们如何知道一个子Query是否会被Cache住呢?遗憾的是现在没有文档做罗列,不过我们根据LRUQueryCache实现类,观察到如下逻辑:

  1. 检查这个Query自身提供的isCacheable方法,如果可以的话继续做下一步判定
  2. 判定对应的Segment是否支持Cache,如果ok,执行缓存动作,进一步判定
  3. 执行QueryCachePolicy相应的策略方法。该方法做了一些枚举,比如TermQuery,MatchAllDocsQuery等是不缓存的,然后会根据使用频次来确定是否加入到缓存。

所以,我们可以简单的找到对应的Query实现,查看相应的isCacheable方法。
比如BinaryDocValuesRangeQuery,也就是Range查询(Int,Double等),对应的isCache方法如下:

public boolean isCacheable(LeafReaderContext ctx) {
return DocValues.isCacheable(ctx, fieldName);
}

/**
* Returns {@code true} if the specified docvalues fields have not been updated
*/
public static boolean isCacheable(LeafReaderContext ctx, String... fields) {
for (String field : fields) {
FieldInfo fi = ctx.reader().getFieldInfos().fieldInfo(field);
if (fi != null && fi.getDocValuesGen() > -1)
return false;
}
return true;
}

相关文章