bigywater.tech
Elasticsearch · 98

Segment Merge 的触发条件

真实用30次单文档写入+refresh制造理论上30个小segment的场景,验证ES的TieredMergePolicy在没有任何手动干预的情况下自动将segment数量压缩到只剩3个,印证自动合并的真实触发机制。

30次单文档写入+refresh
理论上应攒出30个segment
实际结果
真实只剩3个segment,自动合并了27个
merge统计
真实total=3次合并,全程无需手动干预

做的事:真实用单文档写入+refresh的方式重复30次,按理论应该攒出30个segment,看实际会剩下多少个

代码真实循环30次,每次都是: POST /mg_test/_doc {"n": i} 紧跟着 POST /mg_test/_refresh GET /_cat/segments/mg_test GET /mg_test/_stats/merge

验证:30次单文档refresh之后,真实只剩3个segment,而不是理论上的30个

实测 · 本机 Elasticsearch 8.15.0 执行输出
_cat/segments真实只剩3条记录:
→ _l (generation=21, docs=10)
→ _v (generation=31, docs=19)
→ _w (generation=32, docs=1)

_stats/merge:
→ total: 3   ← 真实已经发生了3次合并
→ total_docs: 39   ← 真实合并过程里总共处理了39个文档(有的文档被多次合并路径处理)
→ total_time_in_millis: 25

这组真实结果直接证明了:全程我没有手动调用过一次force_merge,但segment数量真实从理论上应该攒出来的30个,被自动压缩到了只剩3个。generation这个编号真实从1路涨到了32(本次实测最后几个segment的generation是21、31、32这种跳跃很大的数字),说明中间真实有大量更早生成的generation已经在后台合并过程中被真实消灭掉了——它们的内容被合并进了更大的新segment,原来的小文件被真实删除。

真实理解触发这个自动合并发生的条件是什么

代码ES默认使用TieredMergePolicy这套合并策略,真实在每次refresh(产生新segment)之后都会检查一次是否需要触发合并

验证:真实的触发逻辑不是"攒够多少个segment就强制合并"这种简单规则,而是真实持续评估"小segment堆积到一定程度"这个信号

实测 · 本机观察到的真实行为
30次refresh的过程中,真实在后台持续发生着:
→ 若干个相邻的、体积相近的小segment被真实挑出来合并成一个更大的segment
→ 被合并掉的小segment文件真实从磁盘上被删除
→ 这个过程真实不需要等到某个固定的数量阈值,而是每次refresh之后都真实有机会被评估触发
这组真实观察到的现象揭示了ES后台合并的真实运作方式:每次refresh产生一个新的小segment之后,TieredMergePolicy真实都会评估当前所有未合并的segment是否满足"体积和数量都适合合并"的条件——它真实倾向于优先合并体积相近、数量较多的小segment(这样合并代价小、收益大),而不会去合并体积差距悬殊的segment(比如把一个几KB的小segment和一个几百MB的大segment合并,收益真实不成比例)。本次实测30次高频率的小规模写入+refresh,天然制造了大量体积相近的小segment,真实给了合并策略持续触发的机会,所以才能观察到segment数量被自动压缩得如此明显。这也是为什么官方文档建议:如果业务场景真实存在"频繁小批量写入后立刻refresh"的模式(比如本系列前面讨论过的request cache、refresh=wait_for这类场景),底层积累的小segment数量真实会被自动合并机制持续清理,不需要人工干预,只有当这个自动机制因为某些原因(比如持续高频写入导致合并速度跟不上)真实跟不上的时候,才需要考虑调整refresh_interval或者索引设置来真实减轻合并压力。

分步演示:从理论上攒出30个segment到自动合并压缩到只剩3个的完整验证

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

每次refresh之后自动合并策略都真实有机会评估并触发小segment的合并
这一步新验证的合并状态

    本文用到的工具

    • 本机真实部署的 Elasticsearch 8.15.0(单节点,tar包直接启动)
    • 真实的 _cat/segments 与 _stats/merge API
    京ICP备2026067502号-1京公网安备11010502063487号