真实用3次乱序INSERT制造3个各自有序但整体乱序的part,用OPTIMIZE FINAL触发真实合并,验证merge到底在做什么。
代码CREATE TABLE demo.mtest (k UInt64, v String) ENGINE=MergeTree ORDER BY k; INSERT INTO demo.mtest VALUES (3,'c'),(1,'a'); INSERT INTO demo.mtest VALUES (2,'b'),(5,'e'); INSERT INTO demo.mtest VALUES (4,'d');
SELECT name, rows, level FROM system.parts WHERE table='mtest' AND active ORDER BY name; → all_1_1_0 2 rows level=0 all_2_2_0 2 rows level=0 all_3_3_0 1 rows level=0 SELECT _part, k, v FROM demo.mtest ORDER BY _part, k; → all_1_1_0 | 1 | a all_1_1_0 | 3 | c all_2_2_0 | 2 | b all_2_2_0 | 5 | e all_3_3_0 | 4 | d
每个part内部真实是按ORDER BY k排好序的(all_1_1_0里1排在3前面),但3个part放在一起看,k的顺序真实是1,3,2,5,4——完全不是全局有序。这就是为什么ClickHouse的一次SELECT,即使表定义了ORDER BY,如果直接扫多个part,也需要在读取层面做额外的归并才能保证结果有序。
SELECT name, rows, level FROM system.parts WHERE table='mtest' AND active; → all_1_3_1 5 rows level=1 ← 真实3个part合并成了1个,level从0变成1 SELECT _part, k, v FROM demo.mtest ORDER BY k; → all_1_3_1 | 1 | a all_1_3_1 | 2 | b all_1_3_1 | 3 | c all_1_3_1 | 4 | d all_1_3_1 | 5 | e ← 真实全局有序了
每一步都是本文上面用真实OPTIMIZE FINAL跑出来的原始结果。
system.parts(name/rows/level 列)OPTIMIZE TABLE ... FINAL:真实强制触发一次合并(生产环境后台线程会自动做)_part 虚拟列:真实查看每一行属于哪个part