真实跑一条100万行的INSERT,打开ProfileEvents计数器,看清楚数据从客户端到磁盘真实经历了哪几步。
代码CREATE TABLE demo.ipath (k UInt64, v String) ENGINE=MergeTree ORDER BY k; INSERT INTO demo.ipath SELECT number, toString(number) FROM numbers(1000000); SYSTEM FLUSH LOGS; SELECT query_duration_ms, ProfileEvents['InsertedRows'], ProfileEvents['InsertedBytes'], ProfileEvents['MergeTreeDataWriterRows'], ProfileEvents['MergeTreeDataWriterBlocks'], ProfileEvents['FileOpen'] FROM system.query_log WHERE query LIKE '%INSERT INTO demo.ipath%' AND type='QueryFinish';
query_duration_ms: 38 insertedRows: 1000000 insertedBytes: 21888890 (约20.9MB,未压缩前的逻辑字节数) writerRows: 1000000 writerBytes: 21888890 writerBlocks: 1 ← 真实整批100万行只切成了1个写入块 fileOpens: 15 ← 真实这次INSERT在磁盘上打开的文件总数
这条链路真实走了这几步:客户端把100万行数据(numbers()表函数在服务端生成,没走网络)交给INSERT语句的执行器 → 数据先在内存里按ORDER BY k真实排好序、按列组织成内存中的Block → MergeTreeDataWriter真实把这个Block写成磁盘上一个新part的完整文件集合(.bin数据文件、.cmrk2标记文件、primary.cidx索引、checksums.txt等,本文这张2列表真实对应15次文件打开)→ 新part原子地注册进表的元数据,INSERT才算真正完成。
每一步都是本文上面用真实ProfileEvents跑出来的原始数字。
system.query_log ProfileEventsInsertedRows/InsertedBytes/MergeTreeDataWriterBlocks/FileOpen计数器