单节点 MergeTree 能撑住不少 OLAP
场景,但日志、指标、宽表事实一旦超过单机磁盘或 CPU
上限,就要把 同一张逻辑表 切到多个 shard
上。ClickHouse 的 Distributed
引擎不是「又一种存储格式」,而是
查询与写入的路由层:本地表(MergeTree
/ ReplicatedMergeTree)才真正持有
Part;Distributed
表只保存集群拓扑与分片函数。
ReplicatedMergeTree(第
08 篇) 解决 副本一致性与 HA;本文解决
水平分片与跨节点查询。读完应能回答:分片键怎么选、INSERT
落到哪、SELECT 如何在 shard 上并行、何时必须
GLOBAL IN,以及和 PostgreSQL
Citus 的本质差异。
版本锚定:ClickHouse 24.x LTS。集群协调默认写法以 ClickHouse Keeper(兼容 ZooKeeper 协议)为准;仍使用 ZooKeeper 的集群概念相同,路径前缀不同。
一、三层对象:Cluster、Local、Distributed
典型生产拓扑:
flowchart TB
subgraph client [客户端]
CHC[clickhouse-client / JDBC]
end
subgraph coord [协调节点 可选]
DT[Distributed 表 dist.events]
end
subgraph shard1 [Shard 1]
L1[本地表 events_local]
R1[Replica A / B]
end
subgraph shard2 [Shard 2]
L2[本地表 events_local]
R2[Replica A / B]
end
CHC --> DT
DT -->|INSERT 按 sharding key| L1
DT -->|INSERT| L2
DT -->|SELECT 下发子查询| L1
DT -->|SELECT| L2
L1 --- R1
L2 --- R2
| 对象 | 引擎 | 磁盘数据 | 典型命名 |
|---|---|---|---|
| 本地表 | ReplicatedMergeTree |
有 Part | events_local |
| 分布式表 | Distributed |
无 Part,仅元数据 | events |
| 集群定义 | 配置 | 无 | <cluster> in
config.xml |
关键结论:Distributed 表是
视图 +
路由器,不是第三套存储。所有列存文件格式仍遵循 MergeTree
Part 格式(第 02 篇)。
1.1 最小 DDL 示例
-- 在每个 shard 的每个 replica 上创建本地表(简化,省略 ON CLUSTER)
CREATE TABLE events_local ON CLUSTER '{cluster}'
(
event_date Date,
user_id UInt64,
event_type LowCardinality(String),
payload String
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/events_local', '{replica}')
PARTITION BY toYYYYMM(event_date)
ORDER BY (event_date, user_id);
-- 在「入口」库创建 Distributed 表(可在任意节点,常放在统一 query 节点)
CREATE TABLE events ON CLUSTER '{cluster}'
AS events_local
ENGINE = Distributed('{cluster}', currentDatabase(), events_local, cityHash64(user_id));第三参数 events_local 是 各 shard
上的本地表名;第四参数
cityHash64(user_id) 是
分片键表达式。
1.2 宏
{cluster}、{shard}、{replica}
ON CLUSTER 与
ReplicatedMergeTree ZK 路径依赖
macros(通常在
/etc/clickhouse-server/config.d/macros.xml):
<clickhouse>
<macros>
<cluster>prod</cluster>
<shard>01</shard>
<replica>replica_a</replica>
</macros>
</clickhouse>每个物理节点 macros 不同;ON CLUSTER prod
会把 DDL 广播到 remote_servers 里
prod 的所有
host。工程判断:macros 与
remote_servers
不一致是分布式集群最常见的「表存在但路由错 shard」根因。
二、集群配置:remote_servers
与副本权重
config.xml(或
config.d/cluster.xml)定义逻辑 cluster:
<remote_servers>
<prod>
<shard>
<internal_replication>true</internal_replication>
<replica>
<host>ch1.example.com</host>
<port>9000</port>
</replica>
<replica>
<host>ch2.example.com</host>
<port>9000</port>
</replica>
</shard>
<shard>
<internal_replication>true</internal_replication>
<replica>
<host>ch3.example.com</host>
<port>9000</port>
</replica>
<replica>
<host>ch4.example.com</host>
<port>9000</port>
</replica>
</shard>
</prod>
</remote_servers>| 字段 | 含义 |
|---|---|
shard |
水平分片;不同 shard 各持数据子集 |
replica |
同一 shard
内的副本;internal_replication=true
时写入走副本协议 |
internal_replication |
true:Distributed INSERT 只写一份到 shard
内一 replica,由副本链复制 |
weight |
可选;非均匀 shard 容量时调整查询/写入权重 |
与第 08
篇衔接:internal_replication=true
时,Distributed 引擎 不向同一 shard 的所有 replica
各写一份——否则 ReplacingMergeTree
去重语义会被打破。写入目标由 insert_replica
或负载策略选择。
三、分片键:数据分布与查询局部性
分片键是 Distributed 表 DDL 的第四个参数(或
SHARDING_KEY 别名语法,视版本文档)。ClickHouse
计算:
\[ \text{shard\_index} = \bigl(\text{hash}(\text{sharding\_expr}) \bmod N_{\text{shards}}\bigr) + 1 \]
常用
hash:cityHash64、sipHash64、jumpConsistentHash(扩容场景)。
3.1 选型原则
| 目标 | 推荐分片键 | 风险 |
|---|---|---|
| 用户级查询局部性 | cityHash64(user_id) |
超大用户热点 shard |
| 时间范围 + 实体 | (event_date, user_id) 组合 hash |
表达式过复杂难调试 |
| 近似均匀 | 高基数 UUID / 雪花 ID | 无法按业务键 colocate |
| 日志按天 | 不推荐 仅 toDate(ts) |
单日流量打满单 shard |
工程判断:分片键首要保证 写入均匀;其次考虑 最常见 WHERE 能否只扫单 shard。ClickHouse 没有 Citus 的「distribution column = 主键必须」硬约束,但选错键的代价一样:跨 shard 聚合、GLOBAL JOIN 爆炸。
3.2 与 PARTITION BY 正交
PARTITION BY(本地表):Part 目录按月/日切 —— 影响 merge、TTL、删分区。- 分片键:行落到哪个 shard —— 影响分布式路由。
同一 event_date 的行可以分布在所有
shard(分片键含 user_id
时)。常见误区:把
PARTITION BY toYYYYMM(d)
误当分片键,导致每月一个 shard 热点。
3.3 扩容与 resharding
增加 shard 后,旧数据 不会自动重分片。官方路径:
- 新 shard 建空本地表;
- 历史数据
INSERT SELECT或clickhouse-copier/ 第三方工具迁移; - 双写或读路径合并。
jumpConsistentHash 在扩 shard 时比 naive mod
更少迁移行——仍是工程级迁移,无在线透明 resharding(与 Citus
rebalance 对比见 §九)。
四、INSERT 路由
INSERT INTO events ... 进入 Distributed
表时,协调节点:
- 按 block 计算每行的 sharding expr;
- 按 shard 分组;
- 向各 shard 发送
sub-insert(
internal_replication=true时每个 shard 选一个 replica)。
sequenceDiagram
participant C as Client
participant D as Distributed 协调
participant S1 as Shard 1 replica
participant S2 as Shard 2 replica
C->>D: INSERT block
D->>D: 按 cityHash64 分组
D->>S1: INSERT 子 block
D->>S2: INSERT 子 block
S1->>S1: ReplicatedMergeTree 副本链
S2->>S2: ReplicatedMergeTree 副本链
4.1 批量与 async_insert
小 batch 高频 INSERT 会在 每个 shard 各产生 small parts——放大 too many parts(第 15 篇) 风险。缓解:
- 客户端攒 batch(建议 ≥ 10k 行,视列宽调整);
- 表级
async_insert+wait_for_async_insert; - 入口
Buffer表(注意 Buffer 自身坑,见官方 Buffer table)。
不在此给出吞吐数字——须在本集群测
system.events 的 InsertedRows /
InsertedBytes。
4.2
insert_distributed_sync
insert_distributed_sync = 1(session 或
profile)时,Distributed INSERT 等待所有 shard 子 insert
完成再返回。默认异步更快但客户端难以及时捕获单 shard
失败。
4.3 直接写本地表
ETL 若已知 target shard,可绕过 Distributed 直写
events_local——须保证 不会写错
shard。运维脚本常用;应用层一般仍写
Distributed。
五、SELECT:子查询下发与二次聚合
SELECT ... FROM events 的典型计划:
- 协调节点把查询改写成对 每个 shard 的本地表 的子查询(可能带相同 WHERE);
- 各 shard 并行执行(受
max_threads、副本选择影响); - 协调节点对 shard 结果
再聚合(
SUM、COUNT等)。
这与 向量化执行(第 04 篇) 的 pipeline 在协调节点再串一层 Merge 算子。
5.1
副本读:load_balancing
remote_servers 里 replica 的读取策略由
settings 控制,例如:
load_balancing = random(默认类行为)load_balancing = nearest_hostname(同 rack 优先)load_balancing = in_order(故障转移)
只读副本(readonly 用户 +
副本延迟监控)可把 analytics 流量从 leader 拉开——延迟见
system.replicas(第 14 篇)。
5.2 谓词下推与限制
Distributed 会尝试把
WHERE、PREWHERE(见 查询读取路径(第
05 篇))下推到 shard 子查询。但:
- 依赖分片键 无法 剪枝 shard(仍扫全 cluster);
- 某些函数/UDF 可能阻止下推;
LIMIT下推需optimize_skip_unused_shards等优化配合。
-- 若 sharding key 含 user_id,且 WHERE user_id = 123 常数,可只打单 shard(视优化器版本)
SET optimize_skip_unused_shards = 1;
SELECT count() FROM events WHERE user_id = 123 AND event_date >= today() - 7;是否生效以 EXPLAIN /
EXPLAIN PLAN
为准——须本地执行,本文不粘贴计划文本。
5.3 GLOBAL
二次聚合边界
shard 本地执行 GROUP BY k 后,协调节点收到
部分聚合状态,可能再
GROUP BY k 合并。若聚合函数非
decomposable(如 quantileExact
中间态不能简单相加),会触发不同 plan 或报错——设计分布式 SQL
时要查函数是否 combinable。
六、GLOBAL IN 与 GLOBAL JOIN
6.1 普通 IN 的问题
SELECT * FROM events
WHERE user_id IN (SELECT user_id FROM dim_vip_users);若 dim_vip_users 是
仅存在于协调节点 的小表,或未 Distributed
复制,默认 IN 可能在 每个 shard
子查询里本地执行子查询——子表为空或不全,结果错误。
6.2 GLOBAL IN
SELECT * FROM events
WHERE user_id GLOBAL IN (SELECT user_id FROM dim_vip_users);语义:先在 协调节点 执行子查询,把结果 广播 到每个 shard,再各 shard 过滤。
| 模式 | 网络 | 内存 | 适用 |
|---|---|---|---|
| IN | 低 | 低 | 子表已复制到各 shard |
| GLOBAL IN | 高(广播) | 协调节点持全集 | 小子表、临时过滤集 |
| JOIN + 复制引擎 | 中 | 各 shard 本地 | 维表定期同步 |
代价:GLOBAL IN 把协调节点变成
单点内存瓶颈——维表百万行级可能
OOM(max_memory_usage)。
6.3 GLOBAL JOIN
SELECT e.*, d.name
FROM events AS e
GLOBAL INNER JOIN dim_users AS d ON e.user_id = d.id
WHERE e.event_date >= today() - 1;协调节点先拉 dim_users(或子计划),广播到
shard 与 events_local join。宽维表 + 事实表大
scan 时 极慢。
替代架构(工程上更常见):
- 维表复制:每个 shard 建相同
ReplicatedMergeTree维表,定时INSERT SELECT同步;查询用普通JOIN。 - Dictionary(
ENGINE = Dictionary+dictGet):适合小维表、键值查找。 - 预 join 宽表:ETL 阶段打平——牺牲存储换查询简单。
6.4
distributed_product_mode
global / local /
allow 控制分布式 JOIN 行为(见官方
Distributed product mode)。误用 local
可能导致 shard 间笛卡尔积——经典事故模式,第
15 篇会列 symptom。
七、Distributed DDL
与 ON CLUSTER
CREATE TABLE metrics_local ON CLUSTER prod (...);
CREATE TABLE metrics ON CLUSTER prod AS metrics_local
ENGINE = Distributed(prod, currentDatabase(), metrics_local, rand());| 操作 | 注意 |
|---|---|
CREATE ... ON CLUSTER |
依赖 DDLWorker + Keeper/ZK 队列;失败会留
system.distributed_ddl_queue |
DROP TABLE |
先删 Distributed 再删 local,或反之需团队规范 |
RENAME |
24.x 支持有限;生产倾向建新表迁移 |
ALTER mutation |
各 shard 独立 mutation 队列——大表 ALTER 在 N shard 上放大为 N 倍后台压力 |
检查 DDL 队列:
SELECT entry, query, initiator, status, exception_code, exception_text
FROM system.distributed_ddl_queue
ORDER BY entry DESC
LIMIT 20;八、源码与实现锚点
ClickHouse 24.x 源码(A 级):
| 路径 | 职责 |
|---|---|
src/Storages/StorageDistributed.cpp |
Distributed 存储引擎入口 |
src/Storages/Distributed/DistributedSink.cpp |
INSERT 路由与发送 |
src/QueryPipeline/RemoteQueryExecutor.cpp |
远程 subquery 执行 |
src/Interpreters/Cluster.cpp |
cluster 拓扑解析 |
src/Interpreters/DDLWorker.cpp |
ON CLUSTER DDL |
阅读 StorageDistributed::read 与
DistributedSink::write 可串起
读写下推 全路径。
九、与 PostgreSQL Citus / 其它分布式边界
| 维度 | ClickHouse Distributed | Citus |
|---|---|---|
| 定位 | OLAP 分片 + 路由 | PG 扩展,OLTP+HTAP |
| 分片单位 | Part(列存) | 行 / 分片表 |
| 跨 shard JOIN | GLOBAL / 复制维表 | Colocated / repartition |
| 事务 | 无跨 shard 单事务 | 有限分布式事务 |
| Reshard | 离线迁移为主 | rebalance_table_shards |
| 协调节点 | 任意能访问 cluster 的 CH 节点 | Coordinator |
PostgreSQL 内核系列 的 B-Tree、MVCC 语义 不迁移 到 ClickHouse——用 Citus 做 PG 水平扩展,用 ClickHouse 做分析副本或独立 OLAP,是常见分工(第 13 篇 展开选型)。
不写 Spark/Flink 全链路——PLAN 边界外。
十、设计模式与反模式
10.1 推荐模式
星型 + 复制维表
- 事实表
Distributed+cityHash64(user_id); - 维表每 shard 完整副本(小表
ReplicatedMergeTree); - 查询普通
JOIN,避免 GLOBAL。
专用集群入口
- BI 只连 query 节点(无本地 heavy data);
- 写入走 load balancer 到多入口 Distributed;
- 减少业务直连 random shard host。
与 Kafka + MV 配合
- 见 物化视图(第 10 篇);
- Kafka Engine 表 不要 直接 Distributed——通常 Kafka → MV → 本地 MergeTree,Distributed 只包本地表。
10.2 反模式
| 反模式 | 后果 |
|---|---|
分片键 rand() 且无业务过滤 |
任何 GROUP BY 全 cluster 扫描 |
| 大维表 GLOBAL JOIN | 协调节点 OOM、查询超时 |
| 每行 INSERT | N shard × small parts → merge 崩溃 |
忽略 internal_replication 双写 replica |
重复数据、副本冲突 |
| Distributed 当唯一备份 | 无 Part 文件,恢复从 local 表 |
十一、排查清单
- 数据倾斜:
system.parts按hostName()/ 表统计各 shard 行数(需集群级监控或逐 shard 查)。 - 查询慢:
system.query_log看read_rows、ProfileEvents的DistributedConnection*。 - INSERT 失败单
shard:
insert_distributed_sync=1复现;查目标 shardsystem.errors。 - DDL
卡住:
system.distributed_ddl_queue+ Keeper 连通。 - 结果不一致:检查 IN vs GLOBAL IN、维表是否全 shard 同步。
详细系统表见 监控(第 14 篇)。
十二、实验框架(须本地执行)
以下命令框架 未在本环境执行——读者在测试集群验证。
12.1 验证分片分布
-- 在每个 shard 的 events_local 上分别执行,对比 count()
SELECT count() FROM events_local;
-- 或通过 Distributed 查 system 表(若配置允许)
SELECT hostName(), count()
FROM cluster('prod', currentDatabase(), events_local)
GROUP BY hostName();12.2 对比 IN 与 GLOBAL IN 计划
EXPLAIN PLAN
SELECT count() FROM events
WHERE user_id IN (SELECT user_id FROM dim WHERE tier = 'vip');
EXPLAIN PLAN
SELECT count() FROM events
WHERE user_id GLOBAL IN (SELECT user_id FROM dim WHERE tier = 'vip');对比 Expression 节点是否含
GLOBAL
广播——以本地输出为准。
12.3 制造 skew 观察
-- 测试库:故意用常量分片键观察单 shard 膨胀(勿在生产)
CREATE TABLE skew_test_local (...) ENGINE = MergeTree ...;
CREATE TABLE skew_test AS skew_test_local
ENGINE = Distributed('test_cluster', currentDatabase(), skew_test_local, 1); -- 常数键十三、配置项速查
| Setting | 作用 |
|---|---|
optimize_skip_unused_shards |
常量分片键过滤时跳过无关 shard |
optimize_skip_unused_shards_limit |
跳过优化的 shard 数上限 |
insert_distributed_sync |
同步等待各 shard insert |
distributed_product_mode |
JOIN 分布式行为 |
max_query_size |
大 IN 列表解析 |
distributed_group_by_no_merge |
高级:控制二次 GROUP BY |
prefer_localhost_replica |
协调节点本地 replica 优先 |
完整容量相关见 配置与容量(第 16 篇)。
十四、小结
| 问题 | 答案 |
|---|---|
| Distributed 存数据吗? | 否,只路由 |
| 分片键影响什么? | INSERT 目标 shard、部分查询剪枝 |
| GLOBAL IN 何时用? | 小子表未复制到各 shard |
| 与副本关系? | internal_replication=true 时 INSERT 不双写
replica |
| 扩容? | 离线 resharding,无透明 rebalance |
附录 A、GLOBAL JOIN 改写清单
| 原写法 | 问题 | 改写 |
|---|---|---|
GLOBAL JOIN 大维表 |
协调节点 OOM | 每 shard 复制维表 + 普通 JOIN |
IN (SELECT ...) 协调库小表 |
shard 子查询为空 | GLOBAL IN 或复制 |
| 两 fact 表 JOIN | 跨 shard _shuffle | 预聚合 / 同 sharding key colocate |
DISTINCT 子查询过滤 |
广播大 set | JOIN 复制表或 Dictionary |
附录 B、分片键评审问卷
- 写入 QPS 与 batch 大小?小 batch 则先优化 ingest 再谈分片数。
- Top 10 查询是否带 sharding key 等值过滤?
- 是否存在「大用户」skew?是否需要 salt(如
cityHash64(user_id, bucket_id))? - 扩容计划:是否接受 offline copy?
- 维表大小:是否适合每 shard 全量复制?
附录 C、网络与防火墙
Distributed 查询在 shard 间建立 大量 outbound
连接(端口通常 9000/native 或
9440/TLS)。协调节点到各 shard、shard 间
interserver_http(复制)需放通。跨 AZ 部署时
RTT 增加会放大 scatter-gather
延迟——无量化延迟,但架构上应同 AZ 放 query
与 data。
附录 D、术语表
| 术语 | 含义 |
|---|---|
| Scatter-gather | 协调节点下发子查询再合并 |
| Sharding key | Distributed 第四参数表达式 |
| Global subquery | 协调执行后广播到 shard |
附录 E、Distributed 查询计划解读要点
阅读 EXPLAIN PLAN 或 EXPLAIN
时关注:Distributed 节点子计划是否含
GLOBAL;ReadFromStorage 是否只在
subset shard;聚合是否两层 Aggregating。若见
Double aggregation,确认 combinator
正确。协调节点 limit 下推失败会导致各 shard
返回全量再 truncate——高 limit 也危险。
附录 F、双集群 DR
Active-passive 两 cluster 靠对象存储或 replication queue 同步——非 Distributed 内建。DR 演练测 RPO/RTO 用业务指标,本文不写 SLA 数字。
附录 G、负载均衡 insert
多入口节点写同一 Distributed 表时,各入口独立路由——无 central coordinator。入口前 L4 LB 即可;避免 sticky 导致单入口热点,除非 cache 亲和需要。
附录 · 深度补充(系列交叉索引)
深度 1
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
深度 2
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
深度 3
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
深度 4
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
深度 5
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
深度 6
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
深度 7
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
深度 8
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
深度 9
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
深度 10
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
深度 11
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
深度 12
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
深度 13
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
深度 14
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
深度 15
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
深度 16
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
深度 17
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
深度 18
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
深度 19
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
深度 20
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
深度 21
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
深度 22
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
深度 23
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
深度 24
第 09 章与系列其它篇章的交叉:读路径见 第 05
篇;merge 见 第 06
篇;索引见 第 07
篇;副本见 第
08 篇;Distributed 见 第
09 篇;监控见 第 14
篇;故障见 第 15
篇;配置见 第 16
篇。 实施任何 setting 变更前,在 staging 用
system.parts / query_log 建立 24h
基线,变更后再对比——避免无证据调参。
下一篇:物化视图与增量管道
参考资料
- ClickHouse Documentation, Distributed table engine, clickhouse.com/docs, 24.x
- ClickHouse Documentation, Distributed DDL, GLOBAL IN/JOIN
- ClickHouse Source, release-24.x,
src/Storages/StorageDistributed.cpp - ClickHouse Source,
src/Storages/Distributed/DistributedSink.cpp - Citus Documentation, Distributed Tables — 对照边界
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【列存引擎内核】ReplicatedMergeTree
ReplicatedMergeTree 副本协调:Log entry、ClickHouse Keeper/ZooKeeper 路径、副本同步与 recovery。双节点实验步骤(本环境未部署)。24.x LTS 默认推荐 Keeper。
【列存引擎内核】ClickHouse 与 DuckDB 源码级拆解
主选 ClickHouse 拆解 MergeTree 存储格式、向量化执行与分布式协调;DuckDB 作为嵌入式 OLAP 对照。覆盖列存文件布局、merge 机制、跳数索引与生产故障模式,面向数据平台工程师与从 PG/MySQL 转 OLAP 的 DBA。
【列存引擎内核】列存基础与 ClickHouse 架构
行存 vs 列存的带宽、压缩与向量化三角;ClickHouse Server 进程模型、线程池与 MergeTree 引擎家族地图;src/Storages 与 src/Processors 源码入口。对照 PG 行存与 LSM 写优化路径,版本锚定 ClickHouse 24.x LTS。
【列存引擎内核】MergeTree Part 文件格式
ClickHouse MergeTree Part 目录结构:columns.txt、checksums.txt、.bin、.mrk2、primary.idx 语义,Granule 与 Mark 的定位作用,Wide/Compact 布局与 MergeTreeDataPart 源码入口。版本锚定 24.x LTS。