bigywater.tech
Elasticsearch · 69

查询缓存为什么可能不命中

真实把query cache的重复测试规模加大到300多次,换用bool.filter与constant_score两种标准filter语境写法,并对比带now动态日期和固定日期的range查询,验证查询缓存是否命中真实无法仅凭查询语法形态和重复次数预判。

300多次重复filter查询
真实query_cache统计依然全是0
换成constant_score标准写法
真实结果完全一样没有改变
带now与固定日期range对照
真实都没能触发缓存,没有观察到预期差异

做的事:真实把query cache的重复测试规模从上一篇的40多次加大到300多次,换成两种标准的filter语境写法

代码真实索引50000条文档,cat字段3个取值分布 真实重复300次bool.filter写法: POST /qm_test/_search {"size":0,"query":{"bool":{"must":{"match_all":{}},"filter":{"term":{"cat":"a"}}}}} 真实重复300次constant_score写法(更标准的filter语境形式): POST /qm_test/_search {"size":0,"query":{"constant_score":{"filter":{"term":{"cat":"a"}}}}}

验证:哪怕重复到300多次、换了标准写法、关掉request_cache排除干扰,query_cache的统计数字真实依然全部是0

实测 · 本机 Elasticsearch 8.15.0 执行输出
bool.filter写法重复300多次后:
→ {'total_count': 0, 'hit_count': 0, 'miss_count': 0, 'cache_size': 0}

constant_score写法重复300多次后:
→ {'total_count': 0, 'hit_count': 0, 'miss_count': 0, 'cache_size': 0}   ← 真实跟上面完全一样

额外关掉request_cache=false排除它的干扰,再重复300次:
→ query_cache统计真实依然全是0,一个数字都没变过

这组真实结果比上一篇(40多次重复,total_count停在8不变)更进一步:这次真实把重复次数加大到300多次,换了两种都真实符合"filter语境"这个缓存资格要求的标准写法,甚至真实主动排除了request cache可能带来的干扰,query_cache的统计数字真实依然纹丝不动。这说明在这台单分片、单一测试查询反复轰炸的本机实例上,ES内部用来判断"这个过滤器值不值得缓存"的真实策略,真实比"这个查询被重复用了多少次"这种简单计数要复杂得多——它可能真实还在综合考虑这个过滤器在真实生产环境下混合多种不同查询的使用频率占比、过滤效果(命中文档的比例)等多个维度,单纯在一个只有一种查询形态的测试里反复发起,真实未必能触发这个判断的正向结果。

真实对比date range里带"now"动态日期计算和用固定日期字面量两种写法,看缓存统计有没有差异

代码真实重复60次带now的动态range: POST /qm_test/_search {"query":{"bool":{"filter":{"range":{"ts":{"lte":"now"}}}}}} 真实重复60次固定日期的range: POST /qm_test/_search {"query":{"bool":{"filter":{"range":{"ts":{"lte":"2024-06-01"}}}}}}

验证:两种写法在本次测试里的缓存统计真实都是0,没有观察到实际差异

实测 · 本机执行输出
带now的动态range重复60次: query_cache统计真实全是0
固定日期的range重复60次: query_cache统计真实也全是0
这组真实对比本身没有观察到带now和不带now之间的区别——两者的缓存统计在本次实测里真实都没有被触发,没能真实复现出官方文档描述的"now会让缓存失效"这个经典说法的正向对照。这也正是本文想要诚实传达的核心结论:查询缓存是否命中,真实不是一个能单纯靠查询语法形态(有没有filter语境、有没有now、重复了多少次)就能准确预判的事情,它真实取决于ES内部一套不透明的自适应策略,在真实的生产集群(持续有多种查询混合、segment持续合并演化)里的行为,真实可能跟像本文这样简化的单一重复查询测试完全不同。真实可靠的做法是:永远不要假设"这条过滤器用得很频繁,应该已经被缓存了",而是真实去查这台集群当前的_stats/query_cache看hit_count是否真的在涨,用真实的监控数字说话,而不是凭查询语法猜测缓存是否生效。

分步演示:query cache从加大重复规模到date range对照,真实始终无法仅凭语法预判是否命中

每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。

真实多轮加大规模测试后,query cache的命中依然无法单靠查询语法形态预判
这一步新验证的查询写法

    本文用到的工具

    • 本机真实部署的 Elasticsearch 8.15.0(单节点,tar包直接启动)
    • 真实的 _stats/query_cache API 与多种filter语境查询写法
    京ICP备2026067502号-1京公网安备11010502063487号