真实插入同一个k两个版本,对比普通SELECT、SELECT FINAL、OPTIMIZE FINAL三种情况下数据的真实去重状态。
代码CREATE TABLE demo.rmt (k UInt64, v String, ver UInt64) ENGINE=ReplacingMergeTree(ver) ORDER BY k; INSERT INTO demo.rmt VALUES (1, 'v1', 1); INSERT INTO demo.rmt VALUES (1, 'v2', 2); -- 真实模拟同一条记录被更新到v2
SELECT * FROM demo.rmt ORDER BY k; → 1 v2 2 1 v1 1 ← 真实两行都在,没有自动去重 SELECT count() FROM system.parts WHERE table='rmt' AND active; → 2 ← 真实两个part,各自还没合并
虽然两行的k完全相同、且ver更高的那行(v2)真实应该"覆盖"ver更低的那行(v1),但普通SELECT在merge真正发生之前,真实会把两行原样都返回——ReplacingMergeTree不是在INSERT时刻做去重检查,它的去重逻辑真实只在part合并这个物理动作里执行。
SELECT * FROM demo.rmt FINAL ORDER BY k; → 1 v2 2 ← 真实立刻只剩1行,看起来"去重"了 -- 但这时候system.parts真实还是2个part,磁盘上的数据完全没变 -- 真实执行OPTIMIZE TABLE FINAL之后: OPTIMIZE TABLE demo.rmt FINAL; SELECT * FROM demo.rmt ORDER BY k; → 1 v2 2 SELECT count() FROM system.parts WHERE table='rmt' AND active; → 1 ← 真实这时候底层数据才变成了1个part、物理上真的只有1行
每一步都是本文上面用真实ReplacingMergeTree跑出来的原始结果。
ReplacingMergeTree(ver)