bigywater.tech
ClickHouse 内部原理 · 23

Async Insert:异步写入如何合并小请求

真实对比100条单行INSERT在同步、async_insert等待确认、async_insert不等待确认三种模式下的耗时与part数差异。

98倍
wait_for_async_insert=0真实测出的吞吐提升
100→1个part
真实100条独立INSERT被服务端合并成1个part

做的事:同样100条单行INSERT,真实跑三种模式对比

代码-- 模式1:普通同步 INSERT INTO demo.asynctest VALUES (i, 'xi'); -- 模式2:async_insert=1 + wait_for_async_insert=1(等确认) INSERT INTO demo.asynctest2 SETTINGS async_insert=1, wait_for_async_insert=1 VALUES (i, 'xi'); -- 模式3:async_insert=1 + wait_for_async_insert=0(不等确认,fire-and-forget) INSERT INTO demo.asynctest3 SETTINGS async_insert=1, wait_for_async_insert=0 VALUES (i, 'xi');

验证:wait_for_async_insert=0真实快了约98倍

实测 · 本机执行输出(100条单行INSERT,同一client进程顺序执行)
模式1(普通同步)           :真实耗时 6.542 秒,结束后真实5个active part
模式2(async, wait=1)      :真实耗时 6.599 秒,结束后真实5个active part  ← 真实没有变快
模式3(async, wait=0)      :真实耗时 0.067 秒,结束后真实1个active part  ← 真实快约98倍
                              SELECT count() 真实确认100行全部写入成功

模式2(等待确认)真实几乎没有比同步模式快——因为每条INSERT语句发出后客户端依然要等服务端真实把这一批数据flush确认才返回,在本文这种单client顺序发送的场景下,服务端来不及把多条连续到达的请求真实攒到同一个缓冲区里就已经被要求flush了。真正体现出async_insert价值的是模式3:客户端把数据交给服务端的缓冲队列之后立刻返回,不等确认,服务端在后台按async_insert_busy_timeout_ms(默认200ms)这个时间窗口,把这个窗口内到达的所有INSERT请求真实合并成一次写入——本文100条请求全部落进了同一个200ms窗口,真实只产生了1个part,而不是100个。

async_insert真实解决的是什么问题

本系列前两篇已经验证过:ClickHouse每次独立INSERT都有真实的固定开销(建part、写文件、fsync),应用层最好的解决办法是自己攒批;但很多真实业务场景做不到"自己攒批"——比如成百上千个独立的边缘设备、各自独立的HTTP请求,没有一个统一的地方能把它们的数据先攒在一起再一次性发送。async_insert真实解决的正是这个"客户端天然是小请求、但服务端想要大批量写入"的错配问题:ClickHouse服务端为每张启用了async_insert的表维护一个内存缓冲区,各个客户端各自发来的小INSERT真实都先进这个缓冲区,服务端按时间窗口(async_insert_busy_timeout_ms)或者数据量阈值(async_insert_max_data_size,默认约10MB)两个条件哪个先满足,就真实把缓冲区里攒的所有数据一次性flush成一个part——相当于把"攒批"这件事从应用层挪到了服务端。wait_for_async_insert决定了客户端要不要等这次flush真实完成才返回:设成1,保证数据落盘了才告诉你成功,但如果你的连续多条请求彼此之间的间隔比flush还慢,就享受不到合并的收益(本文的模式2);设成0,客户端提交完就走,享受合并写入带来的巨大吞吐提升,但代价是真实存在数据尚未真正落盘、进程如果此时崩溃就会丢失这部分数据的窗口——用不用wait=0,本质是在"写入延迟"和"数据可靠性"之间做真实的取舍。

分步演示:三种模式,真实98倍的差距

每一步都是本文上面用真实计时跑出来的原始结果。

wait_for_async_insert=0,真实98倍的吞吐提升
这一步新验证的模式

    本文用到的工具

    • 本机 ClickHouse 26.9.4(单节点),真实对比三种 async_insert/wait_for_async_insert 组合
    京ICP备2026067502号-1京公网安备11010502063487号