真实对比每次写入都强制refresh与完全禁用refresh两种极端写入模式,验证频繁refresh导致每条文档单独承担一次segment生成开销所带来的约2.1倍真实性能代价,揭示refresh_interval调大能提升写入吞吐的真实原理。
代码索引A: refresh_interval=-1(彻底关闭自动刷新) 索引B: 同样refresh_interval=-1,但真实每次写入都带上refresh=true参数强制刷新 真实各自循环写入2000条独立文档: POST /ri_fast/_doc?refresh=true {"n": i} # 每次都强制刷新 POST /ri_slow/_doc {"n": i} # 完全不触发刷新
每次写入都refresh=true(2000条): elapsed_sec=21.167 完全不触发refresh(2000条): elapsed_sec=10.087 ← 真实慢了约2.1倍
这组真实耗时差距的根源,正是本系列第97篇真实验证过的那个核心事实:每一次refresh都真实会把内存缓冲区里积累的新文档,组织成一个全新的、不可变的Lucene segment文件写入磁盘。如果每条文档写入都真实强制触发一次refresh,就相当于真实把"生成一个全新segment文件"这个本应该批量摊销的开销,真实拆成了2000次、每条文档都单独承担一次,每次真实都要走一遍"打开新段、写入倒排索引结构、让它变得可搜索"这一整套流程,哪怕这个段里只有一条文档。而完全不触发refresh的写入,真实只需要把数据顺序追加进内存缓冲区和translog(本系列第96篇验证过的轻量操作),不需要真实承担反复创建segment文件的开销。
代码真实场景里几乎不会真的完全禁用refresh(那样数据永远搜不到),业务上通常是在 "数据多久之后要能被搜到"和"写入吞吐能有多高"之间权衡一个真实的refresh_interval取值 (默认1秒,日志类写入密集场景常见做法是临时调大到30秒甚至更长)
refresh频率越高(极端情况就是每条写入都refresh): 真实segment生成开销摊销到的写入数越少,每条写入承担的额外成本越高 refresh频率越低(极端情况是完全禁用): 真实segment生成开销摊销到的写入数越多,整体写入吞吐真实越高,但数据变得可搜索的延迟也真实越长
每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。
refresh_interval 设置与 refresh=true 参数