You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 工作机制解析

核心工作原理

  1. 缓存粒度:分片+段+查询
    Query Cache是分片级别的组件,每个分片独立维护自己的缓存。缓存条目以查询哈希值 + 段UUID + 段版本号作为唯一key,存储的是该查询在对应段上匹配的文档ID集合(经过压缩编码)。只有当查询、分片、段三者完全匹配时,才会命中缓存。

  2. 仅缓存过滤上下文查询
    只有处于过滤上下文的查询才会被缓存(这类查询不计算相关性得分,结果可安全复用),比如term、terms、range等叶子过滤查询,以及bool filter这类组合过滤查询。

  3. 缓存的阈值控制
    Elasticsearch不会盲目缓存所有过滤结果:

    • 如果过滤结果匹配的文档数占段总文档数的比例超过阈值(默认10%,可通过index.queries.cache.ignore_above_ratio调整),会跳过缓存——大结果集的缓存性价比极低,计算时间和缓存读取时间差异不大,还会占用大量内存。
    • 当缓存总占用内存超过配置上限(indices.queries.cache.size,你设置为堆内存的10%),会用LRU算法淘汰最久未使用的缓存条目。
  4. 自动失效机制
    当段被合并、删除,或者段的版本发生变化(比如文档更新/删除导致段状态变更),对应的缓存条目会自动失效并被清理。

对你的统计数据的解释

你的统计结果和预期不符,核心原因是缓存统计指标基于每次缓存访问的次数,而非查询请求的次数:

  • 你的查询包含两个独立的叶子过滤查询(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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 14:54:55