2026-06-18 · database / storage
【列存引擎内核】列存基础与 ClickHouse 架构
行存 vs 列存的带宽、压缩与向量化三角;ClickHouse Server 进程模型、线程池与 MergeTree 引擎家族地图;src/Storages 与 src/Processors 源码入口。对照 PG 行存与 LSM 写优化路径,版本锚定 ClickHouse 24.x LTS。





















MergeTree 的数据单元是 Part——一次 insert
block 或一次 merge 输出的
不可变目录。查询、merge、副本同步、mutation
都围绕 Part 展开。搞清
columns.txt、.bin、.mrk2、primary.idx
各干什么,是读 system.parts、诊断 parts
过多、理解 PREWHERE 剪枝的前提。
本文对照 ClickHouse 24.x 官方文档 MergeTree table
engine 与源码
src/Storages/MergeTree/IMergeTreeDataPart*。本环境未安装
ClickHouse,实验步骤可复现,正文不粘贴未执行的命令输出。
flowchart LR
INS[INSERT block] --> SORT[内存按 ORDER BY 排序]
SORT --> NEW[新 Part 目录]
NEW --> ACTIVE[Active Parts 可读]
ACTIVE --> MERGE[Background Merge]
MERGE --> BIGGER[更大 Part]
BIGGER --> OUT[旧 Part Outdated 删除]
| 概念 | 含义 |
|---|---|
| Partition | PARTITION BY 表达式决定的逻辑分桶,对应
data/db/table/ 下子目录或前缀 |
| Part | 分区内一段连续排序数据,目录名含块号与 level,如
202406_1_1_0 |
| Block | 内存 insert 缓冲,落盘成 Part |
同一分区可同时存在 多个 Active Part——读查询合并多 Part 结果(类似 LSM 多层 SST,见 LSM 概览)。
典型 Wide Part(列独立文件),路径形如:
/var/lib/clickhouse/data/<db>/<table>/202406_1_1_0/
├── checksums.txt
├── columns.txt
├── count.txt
├── primary.idx
├── event_date.bin
├── event_date.mrk2
├── user_id.bin
├── user_id.mrk2
├── value.bin
├── value.mrk2
├── minmax_event_date.idx # 若定义 PARTITION BY
└── skp_idx_<name>.idx / .mrk2 # 若定义跳数索引
flowchart TB
PART[Part 目录]
PART --> META[columns.txt / count.txt / checksums.txt]
PART --> PK[primary.idx 稀疏主键]
PART --> COL1[event_date.bin + .mrk2]
PART --> COL2[user_id.bin + .mrk2]
PK --> G1[Granule 0]
PK --> G2[Granule 1]
COL1 --> G1
COL1 --> G2
columns.txt文本格式列清单:名称、类型、默认表达式、编解码器。Part 创建时冻结 schema;ALTER ADD COLUMN 产生新 Part 或 mutation,旧 Part 无新列(读时补默认值)。
checksums.txt各文件大小与 hash(如 CityHash128)。副本 fetch、启动加载时校验完整性。
count.txtPart 总行数,\(O(1)\) 元数据;与 granule 数、Mark 数一致推导关系见 §四。
官方定义:Granule 是 ClickHouse SELECT 时不进一步拆分的最小数据集;每个 granule 含整数行,首行 PK 值写入索引。
控制参数(MergeTree settings):
| Setting | 作用 |
|---|---|
index_granularity |
Mark 间最大行数,默认 8192 |
index_granularity_bytes |
自适应 granule 字节上限,默认 10 MiB |
enable_mixed_granularity_parts |
启用混合粒度 |
行宽极大时,单 granule 可能 少于 8192 行甚至 1
行(单行大于
index_granularity_bytes)。
granule 数估算(理想均匀):
\[ G pprox \left\lceil rac{ ext{rows}}{ ext{index\_granularity}} ight ceil \]
自适应粒度下用实际 Mark
数为准(system.parts.primary_key_bytes_in_memory
等)。
.mrk / .mrk2 /
.mrk3Mark 把 逻辑 granule 映射到 列
.bin 字节位置。
| 扩展名 | 布局 | 每 Mark 内容 |
|---|---|---|
.mrk |
旧固定粒度 Wide | 压缩块偏移 + granule 在块内偏移 |
.mrk2 |
现代 Wide(自适应) | 上述 + granule 行数 |
.mrk3 |
Compact Part | 指向 data.compact.bin |
读路径:primary.idx 定 granule 下标 → 各列
.mrk2 同下标 → 读 .bin 压缩块 →
解压 → 取 granule 行范围。
sequenceDiagram
participant Q as Query
participant PK as primary.idx
participant M as column.mrk2
participant B as column.bin
Q->>PK: PK 谓词 → granule range
Q->>M: 下标 g_lo..g_hi
M->>B: 压缩块偏移
B->>Q: 解压列向量
源码:MergeTreeMarksLoader.cpp、MergeTreeMarkType.h。
.bin
列数据与压缩块每个 .bin 由 多个压缩块
串联;一个压缩块可含 多个 granule
的列数据(列存按列压缩,块边界与 granule 边界不对齐)。
流程:
CODEC(Gorilla, ZSTD)
等)逆序应用。这与 PG 页内 tuple 完全不同:无「页 = 多列行混合」,而是 列方向压缩块。
primary.idxprimary.idx 存 每个 granule
第一条行的 PRIMARY KEY 列值(扁平数组,按 granule
顺序)。数据按 ORDER BY 物理排序,故 PK
单调,可用二分定位谓词范围。
不是:
是:
自 23.5+ 起 primary.idx
可压缩落盘(compress_primary_key),加载时解压进内存;仍保持「小
enough 常驻内存」设计目标(官方 MergeTree 文档
Primary Keys and Indexes)。
PARTITION BY toYYYYMM(d) 时常见:
partition.dat:分区值minmax_<col>.idx:Part 内该列
min/max,用于 partition pruning目录层级:detached/ 存放 DETACH
的 Part;mutation 产生带 mut
后缀的中间态 Part。
| Wide | Compact | |
|---|---|---|
| 列文件 | 每列 .bin + .mrk2 |
data.compact.bin + .mrk3 |
| 触发 | Part 较大(默认 ≥10 MiB) | 小 Part |
| 读少列 | 只读目标列文件 | 可能解压 granule 内多列 |
| merge 后 | 常合并为 Wide | 小 Part 合并 |
Settings:min_bytes_for_wide_part、min_rows_for_wide_part(MergeTree
settings)。
目录名模式:{partition_id}_{min_block}_{max_block}_{level}
level:merge 代数,越大表示经历越多
merge。system.parts
字段:name、rows、bytes_on_disk、level、data_version
等。
IMergeTreeDataPart| 符号 | 文件 | 职责 |
|---|---|---|
IMergeTreeDataPart |
IMergeTreeDataPart.h |
Part 抽象:加载、列、索引 |
MergeTreeDataPartWide |
MergeTreeDataPartWide.cpp |
Wide 布局 |
MergeTreeDataPartCompact |
MergeTreeDataPartCompact.cpp |
Compact 布局 |
MergeTreeDataPartWriter |
MergeTreeDataPartWriter*.cpp |
写 Part |
MergeTreeMarksLoader |
MergeTreeMarksLoader.cpp |
加载 Mark |
MergeTreeIndexGranularity |
MergeTreeIndexGranularity.cpp |
granule 边界 |
加载流程见附录(loadColumnsChecksumsIndexes)。
本环境未安装 ClickHouse。 读者在 24.x 执行:
mkdir -p /tmp/ch-local && cd /tmp/ch-local
clickhouse-local --path ./ch_data --multiquery <<'SQL'
CREATE TABLE t (
d Date,
id UInt64,
s String,
v Float64
) ENGINE = MergeTree()
ORDER BY (d, id);
INSERT INTO t
SELECT '2024-06-01', number, concat('s', toString(number)), number / 3.0
FROM numbers(50000);
SQL查找 Part 路径(因 --path 而异):
find ./ch_data -name 'columns.txt' | head -5
find ./ch_data -name '*.mrk2' | head -5对照 §二
列表检查文件是否齐全。请在本机执行后自行记录
ls 输出,此处不伪造。
系统表(server 模式):
SELECT name, part_type, rows, bytes_on_disk, primary_key_bytes_in_memory
FROM system.parts
WHERE database = currentDatabase() AND table = 't' AND active;part_type 为 Wide 或
Compact。
若需二进制层验证:
# 仅说明方法,未在本环境执行
xxd -l 256 path/to/column.bin | head
xxd -l 128 path/to/primary.idx | headprimary.idx 按 PK
列类型固定宽度存储;.bin 前字节为压缩块
header(具体格式见 CompressedWriteBuffer 与
CompressionCodecFactory 源码)。无实测
hex 时不解读具体字节。
DETACH PART:Part 移到
detached/,不参与查询。checksums.txt 不匹配 → Part 标记
broken,需 ATTACH 或从副本拉取。副本场景见 第 8 篇。
每个 insert block 可产生新 Part;秒级 thousands insert →
merge 跟不上 → parts_to_delay_insert /
parts_to_throw_insert(第 6、15 篇)。
频繁小 batch 宽表可能长期 Compact,读单列仍解压整
granule——调 min_bytes_for_wide_part 或增大
batch。
skp_idx_* 与列 Mark 对齐
granule;定义不当几乎无剪枝(第 7 篇)。
Part = 不可变列文件集合 + 元数据 +
稀疏索引;Granule = 索引与 IO 对齐单位;Mark =
granule 到 .bin 的桥梁。读路径永远:PK
→ granule range → Mark → 压缩块 → 列向量。
上一篇:列存基础
下一篇:压缩与编码
index_granularity两个 Mark 之间最大行数;影响稀疏索引粒度与单次读 granule 行数上限。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):8192。
index_granularity_bytes自适应 granule:限制 granule 预估字节大小,宽行表避免单 granule 过大。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):10485760 (10 MiB)。
enable_mixed_granularity_parts是否启用 index_granularity_bytes 与 index_granularity 混合控制。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):1。
min_bytes_for_wide_partPart 体积超过阈值时使用 Wide 布局(列独立文件)。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):10485760。
min_rows_for_wide_part行数超过阈值转 Wide。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):0。
parts_to_throw_insert活跃 Part 数超过阈值拒绝 insert。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):3000。
parts_to_delay_insert超过阈值开始延迟 insert。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):1000。
merge_max_block_size单次 merge 输出块大小上限。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):8192。
max_bytes_to_merge_at_max_space_in_poolmerge 池有空闲时单任务最大字节。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):161061273600。
number_of_free_entries_in_pool_to_execute_mutationmutation 与 merge 共享池时的调度参数。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):见文档。
compress_marks是否压缩 Mark 文件。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):1。
compress_primary_key是否压缩 primary.idx 落盘(内存仍解压使用)。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):1。
MergeTreeDataPart::loadColumnsChecksumsIndexes()(IMergeTreeDataPart.cpp)依次:
columns.txt 解析列 schema。checksums.txt 校验各文件。count.txt 得行数。primary.idx 与列
Mark(MergeTreeMarksLoader)。skp_idx_*。Part 状态机:Temporary →
PreActive → Active →
Outdated → 删除;merge 产生新 Part 后旧 Part
标记 Outdated。
MergeTreeReaderWide::readRows() 按 Mark
Range 对每个请求列:
.mrk2 得压缩块偏移与 granule
内偏移。CachedCompressedReadBuffer 读
.bin 压缩块。ISerialization +
CompressionCodec)还原列片段。小 Part 使用 data.compact.bin +
data.compact.mrk3;宽表频繁小 insert
时文件数少,但读单列可能解压同 granule
内其他列——适合窄表或总是读全列的 projection。
DDL 示例:value Float64 CODEC(Gorilla, ZSTD)
表示 先 Gorilla 专用编码,再 ZSTD
通用压缩。读路径逆序解压。
内置通用压缩:NONE、LZ4、ZSTD(及
level 变体)。专用编码见官方 Compression codecs
表。
对序列 \(x_1,\ldots,x_n\),Delta 存 \(d_i = x_i - x_{i-1}\)(首元素规则见实现)。DoubleDelta 对 \(d_i\) 再差分,适合时间戳等二阶平滑序列。
Pelkonen et al., Gorilla: A Fast, Scalable, In-Memory Time Series Database, VLDB 2015。XOR 压缩相邻浮点值的 leading/trailing zero 相同前缀。
内部维护字典 + 索引列;对低基数 String/Enum 减少存储与 group by 字典优化。与 Plain 编码选择属于 DDL 设计(非自动 TOAST)。
Nullable 列额外
.null.bin(视版本/序列化而定);默认值列可能仅
.default 文件。读路径需合并 null map;宽表
Nullable 多会增加文件数。
固定长度类型序列化紧凑;仍受 granule 与 codec 影响。随机 UUID 作 ORDER BY 前缀会导致稀疏索引几乎无效——工程上避免。
DateTime64 排序键常用 DoubleDelta;插入时区
session_timezone 与显示无关存储。跨时区报表在
SQL 层转换,不在 Part 内改。
Enum 存整数标签;LowCardinality 字典适合低基数。高基数 String 强行 LowCardinality 字典膨胀,压缩与查询均变差。
Nested 在磁盘展开为多个子列 Array;JSON 类型(若启用)路径提取有独立序列化。宽 Nested 增加 Part 文件数,merge 成本上升。
物化列随 insert 计算持久化,占独立
.bin。适合重复表达式,但增加写放大与存储;与 MV
目标表不同。
TTL DELETE 在 merge 时删
granule;ALTER DROP PARTITION 整分区移除
Part。后者运维更干净;前者适合行级过期。
FREEZE 硬链 Part 到 shadow/
目录做一致性快照;与副本 fetch 互补。恢复需
ATTACH PART 流程,见官方 Backup 文档。
手动 DETACH PART 将目录移入
detached/,不参与查询与 merge。排障错误 Part
或迁移数据时使用;attach 前需校验 checksums。
多客户端 insert 各自形成 Part;无跨客户端单 block 合并。高并发小 insert 是 parts 爆炸主因——应用侧 batch 或 async_insert 缓冲。
强制 merge 至单 Part(分区内)并应用 Replacing 等语义。生产大表慎用:IO 峰值、长时间锁表语义以文档为准。更适合维护窗口。
逐列
data_compressed_bytes、data_uncompressed_bytes、compression_codec——压缩实验应用此表而非猜。见第
3 篇 benchmark 框架。
频繁查询受益
mark_cache、primary_index_cache(配置与
metric 见文档)。冷查询首次读盘仍取决于 Mark/PK 大小。
若查询 ORDER BY 与表排序键一致且无大幅改写,优化器可走 ReadInOrder 减少全量排序内存。与 merge 物理排序强相关。
ReplicatedMergeTree 上 ON CLUSTER DDL 通过
distributed DDL queue;与 Part 级复制不同层。第 8 篇聚焦
Part 同步。
24.x 推荐 Keeper(Raft);ZK 路径约定兼容。新集群优先 Keeper,减少 JVM 依赖与 tail latency。
insert_quorum 要求 N 副本确认 Part;与 async
insert 策略互斥需谨慎。金融场景可能启用,吞吐下降。
副本 system.replication_queue 中
GET_PART 失败会重试;Broken Part
需人工 SYSTEM DROP REPLICA / 重新同步。监控
last_exception。
PostgreSQL 作源时,MaterializedPostgreSQL 或
CDC 工具写入 MergeTree;PG 仍行存 MVCC,CH 侧 append
Part。一致性窗口由复制协议决定。
日志写入 CH 常用 Kafka 引擎 + MV(第 10 篇规划)。ingest 侧 batch 大小直接决定 Part 尺寸——与 可观测性系列 管道设计联动。
高压缩率 + 宽 granule 可能 CPU bound(解压);NVMe
上低压缩可能 IO bound。system.events 中
OSIOWait* vs UserTime
辅助判断,需本机 profile。
max_threads 默认与 CPU 核相关;过大线程增加
Part 并行读开销与内存。HTAP 混部应限制 CH 查询线程池。
system.metrics 的
MemoryTracking、MergesMutationsMemoryTracking;OOM
前常见 merge 与 big aggregation 同抢内存。
mutation 产生 xxx_mutyyy 中间 Part;完成后旧
Part outdated。system.mutations 的
parts_to_do 反映剩余工作量。
VersionedCollapsing 用 (Sign, Version)
对消;比纯 Collapsing 更适合乱序变更。merge
前查询仍需应用层理解 sign。
仅数值列默认 sum;非键列需显式指定 summing 列。非 sum 列取任意值(merge 确定性规则见文档)。
存 AggregateFunction 状态;查询需
-Merge 组合器。适合预聚合管道,schema
设计门槛高。
按时间精度 rollup 规则在 config 定义;监控迁移场景专用。与普通 Summing 不同。
S3 作 disk 时 Part 对象化;读延迟高于本地
SSD。merge 仍发生,网络带宽成为瓶颈。
零拷贝 replication 到 S3 磁盘配置见官方;副本 fetch 可走对象存储。与第 8 篇 queue 类型相关。
单分区过大 merge 慢;过多分区 metadata
膨胀。按天/租户合理切分;避免
PARTITION BY rand()。
PK 列过多/long String 增大 primary.idx
与内存。仅前缀必要列;其余放 ORDER BY 后缀或跳数索引。
GRANULARITY 过大索引粗;过小索引体积接近逐 granule。默认 1–4 需按列选择性实验(第 7 篇)。
Bloom 仅跳过 granule;假阳性多读 granule 仍正确。无 false negative。
列值在 granule 内分布宽但谓词窄,minmax 无法跳过——需更细 ORDER BY 或 bloom。
set 索引 granule 内 distinct 超上限则退化;高基数列不适用 set。
向量相似搜索非 MergeTree 经典跳数索引范畴;24.x 实验特性不在此系列承诺。
EXPLAIN PIPELINE 展示 Processor 图;与
EXPLAIN indexes=1
互补。本环境无实例不贴输出。
Analyzer 产出 QueryPlan,再转 Pipeline。PREWHERE 下推在此阶段决定;SQL 写法影响是否自动 PREWHERE。
常量谓词与 PK 范围交集在优化期计算;参数化查询仍受益 prepared 边界。
ReplacingMergeTree 的 FINAL
在查询期归并;替代方案 MV 去重或应用层
argMax。
较新版本 lightweight delete 标记删除 granule;与 mutation 路径不同。以 24.x 文档为准是否 GA。
单 insert block 原子;跨 Part 无 MVCC 快照隔离。勿与 PG MVCC 类比。
嵌入式 clickhouse-local 适合 Part
格式实验(第 2 篇);与 server 共用 MergeTree 代码路径。
大版本升级前查 release notes Part 格式变更;通常向后读旧 Part,merge 逐步重写。
checksums.txt 使用 CityHash128 等;损坏 Part
拒绝加载保护下游。
ALTER MODIFY COLUMN 可能触发 mutation 重写;类型不兼容需中间列。
字典非 MergeTree Part;JOIN 字典与 MergeTree scan 是不同 IO 路径。
Distributed 上 GLOBAL IN 广播维表(第 9 篇);本地 MergeTree 无此问题。
官方 hits 数据集适合验证读路径;下载与导入步骤见 clickhouse.com/docs getting started。
引用外部 benchmark 必须标注来源;自测需 3 轮中位数与环境表(WRITING_GUIDE)。
MergeTree:StorageMergeTree →
IMergeTreeDataPart →
MergeTreeReaderWide →
MergeTreeDataMergerMutator。执行:PipelineExecutor
→ IProcessor。
24.x LTS 安全/backport 周期见官网;生产锚定 LTS 而非 latest。
运维读 Part
状态时常用列:database、table、name(目录名)、part_type(Wide/Compact)、rows、bytes_on_disk、bytes_on_disk_uncompressed、primary_key_bytes_in_memory、marks_bytes_on_disk、level、data_version、is_frozen。active=0
表示已被 merge 替换但未物理删除。与 LSM SST 层数
类似,应监控每表 active part 数趋势。
system.merges 展示当前运行中的
merge:database、table、elapsed、progress(0–1)、num_parts、result_part_name、total_size_bytes_uncompressed。长时间
progress 不动可能磁盘 IO 饱和或单 Part
过大。merge_max_block_size
影响单次归并行数。
启用 query_log
后,read_rows、read_bytes、result_rows
对比可验证索引剪枝是否生效。PREWHERE 优化通常降低
read_bytes 而 read_rows 仍含
granule 内过滤前行数。本系列不在此环境给出样本数值。
除表级 merge_tree settings 外,insert 受
max_insert_block_size、min_insert_block_size_rows、async_insert(24.x
异步 insert 特性以文档为准)影响。小 block 直接对应小
Part——平台侧应强制 batch 或 Buffer 引擎。
TTL MOVE 与 storage_policy 可将 Part
移至慢盘/对象存储。merge 与 fetch
路径需保证目标卷有足够空间;system.disks 与
system.storage_policies 描述卷与策略。
24.x 支持 projection 预聚合/排序副本。属于高级 DDL,本系列主路径不展开;知晓其存在可避免与跳数索引职责混淆——projection 是额外 Part 子集,非跳数索引。
SAMPLE BY 与 SAMPLE
子句依赖排序键哈希;与主键剪枝独立。日志采样分析常用,但不替代正确
ORDER BY 设计。
Nullable 列额外
.null.bin(视版本/序列化而定);默认值列可能仅
.default 文件。读路径需合并 null map;宽表
Nullable 多会增加文件数。
固定长度类型序列化紧凑;仍受 granule 与 codec 影响。随机 UUID 作 ORDER BY 前缀会导致稀疏索引几乎无效——工程上避免。
DateTime64 排序键常用 DoubleDelta;插入时区
session_timezone 与显示无关存储。跨时区报表在
SQL 层转换,不在 Part 内改。
Enum 存整数标签;LowCardinality 字典适合低基数。高基数 String 强行 LowCardinality 字典膨胀,压缩与查询均变差。
Nested 在磁盘展开为多个子列 Array;JSON 类型(若启用)路径提取有独立序列化。宽 Nested 增加 Part 文件数,merge 成本上升。
物化列随 insert 计算持久化,占独立
.bin。适合重复表达式,但增加写放大与存储;与 MV
目标表不同。
TTL DELETE 在 merge 时删
granule;ALTER DROP PARTITION 整分区移除
Part。后者运维更干净;前者适合行级过期。
FREEZE 硬链 Part 到 shadow/
目录做一致性快照;与副本 fetch 互补。恢复需
ATTACH PART 流程,见官方 Backup 文档。
手动 DETACH PART 将目录移入
detached/,不参与查询与 merge。排障错误 Part
或迁移数据时使用;attach 前需校验 checksums。
多客户端 insert 各自形成 Part;无跨客户端单 block 合并。高并发小 insert 是 parts 爆炸主因——应用侧 batch 或 async_insert 缓冲。
强制 merge 至单 Part(分区内)并应用 Replacing 等语义。生产大表慎用:IO 峰值、长时间锁表语义以文档为准。更适合维护窗口。
逐列
data_compressed_bytes、data_uncompressed_bytes、compression_codec——压缩实验应用此表而非猜。见第
3 篇 benchmark 框架。
频繁查询受益
mark_cache、primary_index_cache(配置与
metric 见文档)。冷查询首次读盘仍取决于 Mark/PK 大小。
若查询 ORDER BY 与表排序键一致且无大幅改写,优化器可走 ReadInOrder 减少全量排序内存。与 merge 物理排序强相关。
src/Storages/MergeTree/IMergeTreeDataPart.cppMergeTreeDataPartWide.cpp,
MergeTreeMarksLoader.cpp ###
index_granularity两个 Mark 之间最大行数;影响稀疏索引粒度与单次读 granule 行数上限。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):8192。
index_granularity_bytes自适应 granule:限制 granule 预估字节大小,宽行表避免单 granule 过大。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):10485760 (10 MiB)。
enable_mixed_granularity_parts是否启用 index_granularity_bytes 与 index_granularity 混合控制。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):1。
min_bytes_for_wide_partPart 体积超过阈值时使用 Wide 布局(列独立文件)。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):10485760。
min_rows_for_wide_part行数超过阈值转 Wide。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):0。
parts_to_throw_insert活跃 Part 数超过阈值拒绝 insert。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):3000。
parts_to_delay_insert超过阈值开始延迟 insert。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):1000。
merge_max_block_size单次 merge 输出块大小上限。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):8192。
max_bytes_to_merge_at_max_space_in_poolmerge 池有空闲时单任务最大字节。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):161061273600。
number_of_free_entries_in_pool_to_execute_mutationmutation 与 merge 共享池时的调度参数。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):见文档。
compress_marks是否压缩 Mark 文件。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):1。
compress_primary_key是否压缩 primary.idx 落盘(内存仍解压使用)。
官方文档默认值(24.x,以实例
system.merge_tree_settings
为准):1。
MergeTreeDataPart::loadColumnsChecksumsIndexes()(IMergeTreeDataPart.cpp)依次:
columns.txt 解析列 schema。checksums.txt 校验各文件。count.txt 得行数。primary.idx 与列
Mark(MergeTreeMarksLoader)。skp_idx_*。Part 状态机:Temporary →
PreActive → Active →
Outdated → 删除;merge 产生新 Part 后旧 Part
标记 Outdated。
MergeTreeReaderWide::readRows() 按 Mark
Range 对每个请求列:
.mrk2 得压缩块偏移与 granule
内偏移。CachedCompressedReadBuffer 读
.bin 压缩块。ISerialization +
CompressionCodec)还原列片段。小 Part 使用 data.compact.bin +
data.compact.mrk3;宽表频繁小 insert
时文件数少,但读单列可能解压同 granule
内其他列——适合窄表或总是读全列的 projection。
把当前热点继续串成多页阅读,而不是停在单篇消费。
2026-06-18 · database / storage
行存 vs 列存的带宽、压缩与向量化三角;ClickHouse Server 进程模型、线程池与 MergeTree 引擎家族地图;src/Storages 与 src/Processors 源码入口。对照 PG 行存与 LSM 写优化路径,版本锚定 ClickHouse 24.x LTS。
2026-06-18 · database / storage
ClickHouse 列压缩:LZ4、ZSTD、Delta、DoubleDelta、Gorilla 时序编码与列类型关系;CODEC 链顺序、LowCardinality 与 PG TOAST 对照。压缩比须本机实测,本文不编造倍数。
2026-06-18 · database / storage
ClickHouse Block 列向量 batch、IProcessor Pipeline 与 filter/project/aggregate 向量实现;对照 PostgreSQL 火山模型 ExecProcNode。源码入口 src/Processors、src/Columns。24.x LTS。
2026-06-18 · database / storage
MergeTree SELECT 读路径:Mark Range 定位 Granule、PREWHERE 与 WHERE、Part 级并行与 max_threads。EXPLAIN indexes=1 解读方法。24.x LTS,无伪造 EXPLAIN 输出。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。