为什么说ck的delete很难用,在生产中又是怎样的灾难
·
ClickHouse(CK)里的 DELETE,为什么在生产环境中被称作“难用”,甚至可能成为“灾难”?
一、ClickHouse DELETE 的本质
-
ClickHouse 是列式存储 + MergeTree 系列表引擎
- 数据按 part(数据块) 存储
- 写入是 append-only
- 查询通过合并多个 part 实现
-
DELETE 不是真正逐行删除
- DELETE 语句会生成 标记(mutation)
- 标记要删除的行,但物理删除发生在 后台 merge 过程中
-
DELETE 的执行流程
用户执行 DELETE -> CK 生成 mutation -> mutation 标记数据块中对应行 -> merge 背景任务执行,物理删除行
注意:这不是即时删除,删除完成可能要几分钟甚至几小时,取决于数据量和后台 merge 任务。
二、为什么 DELETE 很难用
1️⃣ 延迟高(不是实时生效)
- 大量数据 DELETE 可能几分钟甚至几个小时才生效
- 查询仍然可能返回被删除的数据(直到 mutation 完成)
2️⃣ 资源消耗巨大
- DELETE 触发 merge
- 大量行被标记后,后台 merge 会 扫描、重写整个数据块
- 数据量大时,CPU、IO、磁盘压力非常大
- 对生产表尤其是大表,可能导致查询延迟飙升
3️⃣ 并发冲突
- DELETE mutation 与 INSERT、OPTIMIZE、TTL 等操作竞争资源
- 可能导致 merge 堵塞、查询变慢、甚至部分 mutation 失败
4️⃣ 无法精准控制
- DELETE 只能按 条件匹配行
- 对大表删除全表或大范围行几乎是灾难
- 小心误删:一旦 DELETE 执行,虽然不是立即物理删除,但 mutation 会生成,回滚困难
三、生产环境中的灾难案例
-
大表误删
- DELETE 条件写错,覆盖几十亿行
- mutation 触发背景 merge
- CPU/IO 飙升,查询变慢,业务系统卡顿
-
高并发 DELETE
- 与 INSERT / SELECT 并行执行
- merge 队列堆积
- 影响整个数据库实例性能
-
TTL + DELETE 混用
- TTL 触发 merge + DELETE mutation
- 数据块被频繁重写,导致磁盘 I/O 高峰
- 查询响应时间延长
-
删除大范围行
- CK 不是行存储,删除大量行等于 全表重写
- 对数十亿行大表,几小时甚至几十小时才能完成
所以 CK DELETE 只能算 “轻量标记删除 + 小范围行删除”,不适合频繁大规模删除
四、生产中可替代方案
-
分区管理
- 用 DROP PARTITION 替代 DELETE 大范围删除
- 删除粒度:分区而不是行
- 性能最好,立即生效
-
TTL + 覆盖写
- 对旧数据用 TTL 自动过期
- 新版本覆盖写,而不是直接 DELETE
-
ReplacingMergeTree / CollapsingMergeTree
- 用版本列或 sign 列实现“逻辑删除”
- 不直接物理删除行
-
副本表 / 历史表
- 如果数据量大,不删除原表,写入新的快照表
- 查询时只查询快照表
五、总结
| 特性 / 风险 | 描述 |
|---|---|
| DELETE 本质 | append-only + mutation 标记,不是即时物理删除 |
| 延迟 | 大表删除可能几小时后才生效 |
| 资源消耗 | 背景 merge 会重写数据块,CPU/IO 占用高 |
| 并发问题 | DELETE 与 INSERT/SELECT 冲突,可能堵塞 merge |
| 风险场景 | 大表误删、高并发删除、TTL + DELETE 混用 |
💡 结论:
ClickHouse 的 DELETE 不是行级即时删除,生产环境大表频繁 DELETE 会导致性能灾难。
推荐策略:用分区 DROP、TTL 或逻辑删除替代 DELETE。
更多推荐
所有评论(0)