bigywater.tech
ClickHouse 内部原理 · 11

Granule:为什么默认大约 8192 行一个索引粒度

真实关掉字节自适应粒度,验证8192是不是精确的行数边界,再打开默认配置看字节数是怎么真实提前截断granule的。

123→124
关闭/打开字节自适应,同样100万行的marks数真实不同
≈510行/granule
2000字节大行时granule真实被字节上限提前截断

做的事:真实关掉自适应粒度,看8192是不是精确的

代码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;

验证:关掉自适应之后,marks真实精确等于ceil(行数/8192)

实测 · 本机执行输出(index_granularity_bytes=0,纯按行数)
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万行真实变成了124个mark

实测 · 本机执行输出(默认配置,(UInt64,String)两列表)
同样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真实从19.x起默认用自适应索引粒度(adaptive index granularity):一个granule的真实边界不是死板的"凑满8192行",而是index_granularity行数和index_granularity_bytes字节数(默认10MB)两个上限中先到者为准——行很小的表(比如本文第一个UInt64表)通常是行数先达到8192触发切分;但如果每行很大(比如本文2000字节的大String列),granule会真实远小于8192行就先被字节上限截断,本文的g5表验证出真实的granule大小是510行左右而不是8192行。这也真实解释了为什么100万行的(UInt64,String)表关掉自适应是123个mark,打开自适应之后真实变成了124个——两列表的数据在写入过程中字节数的增长速度不是完全线性的,某个granule真实提前因为字节数摸到了阈值而被截断,导致总mark数比纯按行数计算多出了1个。

分步演示:从精确8192行到被字节数提前截断的granule

每一步都是本文上面用真实ClickHouse跑出来的原始marks数。

8192只是行数上限,字节上限真实可能先到
这一步新验证的场景

    本文用到的工具

    • 本机 ClickHouse 26.9.4(单节点),真实的 system.parts marks/rows 列
    • SETTINGS index_granularity_bytes=0:真实关闭字节自适应粒度做对照
    京ICP备2026067502号-1京公网安备11010502063487号