真实关掉字节自适应粒度,验证8192是不是精确的行数边界,再打开默认配置看字节数是怎么真实提前截断granule的。
代码CREATE TABLE demo.g4 (k UInt64) ENGINE=MergeTree ORDER BY k SETTINGS index_granularity_bytes=0; -- 真实关掉字节自适应,纯按行数切granule INSERT INTO demo.g4 SELECT number FROM numbers(1000000); SELECT marks, rows FROM system.parts WHERE table='g4' AND active;
16384行(正好2×8192)→ marks=2 (真实精确整除) 16385行(多1行) → marks=3 (真实多出的1行独占一个新granule) 1000000行 → marks=123 (真实等于 ceil(1000000/8192)=122.07→123)
关掉字节自适应之后,index_granularity=8192真实是精确按行数切的:每凑够8192行(或者数据插入完毕时剩下不足8192行的尾巴)就真实切一个新granule,marks数真实精确等于ceil(总行数/8192),没有任何意外的多余mark。
同样100万行,默认 index_granularity_bytes=10MB(未关闭):
SELECT marks, rows FROM system.parts WHERE table='gtest' AND active;
→ marks=124, rows=1000000 ← 真实比纯按行数多出1个mark
再用大行验证字节先到、提前截断的场景:
CREATE TABLE demo.g5 (k UInt64, big String) ENGINE=MergeTree ORDER BY k
SETTINGS index_granularity=8192, index_granularity_bytes=1048576; -- 1MB
INSERT INTO demo.g5 SELECT number, repeat('x',2000) FROM numbers(50000);
SELECT marks, rows FROM system.parts WHERE table='g5' AND active;
→ marks=98, rows=50000 ← 真实远小于 ceil(50000/8192)=7,等等,98比7大很多
50000/98 ≈ 510行/granule,510行×2000字节 ≈ 1.02MB ≈ 真实正好卡在1MB字节上限每一步都是本文上面用真实ClickHouse跑出来的原始marks数。
system.parts marks/rows 列SETTINGS index_granularity_bytes=0:真实关闭字节自适应粒度做对照