Elasticsearch Query Cache未按预期工作,请求原理解析
关于Elasticsearch Query Cache的疑问
我有一个已启用Query Cache的索引,该缓存占用10%的堆内存。为了解其工作机制,我重置了索引并清除所有统计数据。
执行查询前的缓存统计
"query_cache": { "memory_size": "0b", "memory_size_in_bytes": 0, "total_count": 0, "hit_count": 0, "miss_count": 0, "cache_size": 0, "cache_count": 0, "evictions": 0 }
查询语句(过滤上下文)
{ "query": { "bool": { "filter": [{"term": {"id": "1666"}}, {"terms": {"skip": [0]}}] } } }
该查询返回约4000条文档,执行3次后的缓存统计如下:
执行3次后的缓存统计
"query_cache": { "memory_size": "6.7kb", "memory_size_in_bytes": 6932, "total_count": 6, "hit_count": 1, "miss_count": 5, "cache_size": 1, "cache_count": 1, "evictions": 0 }
我预期首次执行时miss_count为1,后续执行hit_count递增,但实际情况并非如此。
段统计信息
index - my_index shard - 0 prirep - p segment - _jj generation - 703 docs.count - 28192 docs.deleted - 190 size - 163.4mb size.memory - 0 committed - true searchable - true version - 9.5.0 compound - true
恳请解释该缓存的工作原理?
Elasticsearch Query Cache 工作机制解析
核心工作原理
缓存粒度:分片+段+查询
Query Cache是分片级别的组件,每个分片独立维护自己的缓存。缓存条目以查询哈希值 + 段UUID + 段版本号作为唯一key,存储的是该查询在对应段上匹配的文档ID集合(经过压缩编码)。只有当查询、分片、段三者完全匹配时,才会命中缓存。仅缓存过滤上下文查询
只有处于过滤上下文的查询才会被缓存(这类查询不计算相关性得分,结果可安全复用),比如term、terms、range等叶子过滤查询,以及bool filter这类组合过滤查询。缓存的阈值控制
Elasticsearch不会盲目缓存所有过滤结果:- 如果过滤结果匹配的文档数占段总文档数的比例超过阈值(默认10%,可通过
index.queries.cache.ignore_above_ratio调整),会跳过缓存——大结果集的缓存性价比极低,计算时间和缓存读取时间差异不大,还会占用大量内存。 - 当缓存总占用内存超过配置上限(
indices.queries.cache.size,你设置为堆内存的10%),会用LRU算法淘汰最久未使用的缓存条目。
- 如果过滤结果匹配的文档数占段总文档数的比例超过阈值(默认10%,可通过
自动失效机制
当段被合并、删除,或者段的版本发生变化(比如文档更新/删除导致段状态变更),对应的缓存条目会自动失效并被清理。
对你的统计数据的解释
你的统计结果和预期不符,核心原因是缓存统计指标基于每次缓存访问的次数,而非查询请求的次数:
- 你的查询包含两个独立的叶子过滤查询(
term(id:1666)和terms(skip:[0])),每次执行查询时,Elasticsearch会分别对这两个查询发起缓存检查,3次查询就会产生6次缓存访问(对应total_count=6)。 - 其中一个过滤查询的结果符合缓存条件(匹配文档占比低),第一次访问未命中(
miss_count+1)并被缓存,第二次访问命中(hit_count+1);另一个过滤查询的结果因匹配占比过高,未被缓存,每次访问都未命中(3次×1=3次miss),再加上第一个查询第三次访问可能因段状态微变(比如已删除文档的影响)未命中,最终总miss次数为5,hit次数为1。 cache_count=1也验证了只有一个过滤查询的结果被成功缓存。
内容的提问来源于stack exchange,提问作者Meghana S
相关产品推荐
相关产品推荐

