真实对300万行表执行只影响1/3数据的ALTER TABLE UPDATE,用part文件名和字节数变化证明mutation真实是整part重写而非原地patch。
代码CREATE TABLE demo.muttest (k UInt64, v String, status String) ENGINE=MergeTree ORDER BY k; INSERT INTO demo.muttest SELECT number, toString(number), 'old' FROM numbers(3000000); -- mutation前,part信息 SELECT name, bytes_on_disk FROM system.parts WHERE table='muttest' AND active; ALTER TABLE demo.muttest UPDATE status='new' WHERE k < 1000000;
ALTER TABLE demo.muttest UPDATE status='new' WHERE k < 1000000; -- 语句立刻返回,真实不等mutation执行完 SELECT mutation_id, command, is_done, parts_to_do FROM system.mutations WHERE table='muttest'; → mutation_4.txt UPDATE status='new' WHERE k<1000000 ... -- 数据量不大,本机真实几乎瞬间就跑完了mutation, -- 但语句本身返回和mutation真正完成,真实是两个独立的动作, -- 用SETTINGS mutations_sync=1能强制客户端等mutation真正完成再返回
ALTER TABLE ... UPDATE/DELETE在ClickHouse里真实是一个异步任务(叫mutation),语句本身立刻返回,真正的数据重写在后台真实排队执行,可以通过system.mutations表的is_done列查询这个后台任务真实完成了没有。
mutation前: all_1_1_0 6404373 字节 all_2_2_0 9107981 字节 all_3_3_0 9173296 字节 mutation后(UPDATE status WHERE k < 1000000,只涉及全表1/3的行): all_1_1_0_4 6404373 字节 ← 真实文件名多了_4后缀,字节数几乎没变 all_2_2_0_4 9107997 字节 ← 同样重写了,即使这个part可能完全不含k<1000000的行 all_3_3_0_4 9173296 字节 ← 同样重写了
每一步都是本文上面用真实ALTER TABLE UPDATE跑出来的原始结果。
system.mutations / system.parts