ClickHouse 查询性能分析是优化查询效率、理解执行计划、排查慢查询的关键能力。其中,EXPLAIN 命令是核心工具,它能揭示 ClickHouse 如何执行一条 SQL,包括执行阶段、数据扫描量、并行度、索引使用等。
本篇将全面、深入地详解 ClickHouse 的 EXPLAIN 功能,帮助你掌握如何分析查询性能、识别瓶颈、优化 SQL。
🔍 一、EXPLAIN 是什么?
EXPLAIN 用于查看 SQL 查询的执行计划,不真正执行查询,返回查询的逻辑或物理执行信息。
类似于 MySQL 的
EXPLAIN,但 ClickHouse 的EXPLAIN更强大,支持多级输出。
🧩 二、EXPLAIN 的四种模式
ClickHouse 支持通过 格式后缀 控制 EXPLAIN 输出内容:
| 模式 | 命令 | 说明 |
|---|---|---|
| 1. 执行计划(Plan) | EXPLAIN | 默认模式,显示执行树 |
| 2. 管道信息(Pipeline) | EXPLAIN PIPELINE | 显示执行流水线(线程、块大小) |
| 3. 估算信息(Estimate) | EXPLAIN ESTIMATE | 显示数据扫描行数、分区数 |
| 4. AST(抽象语法树) | EXPLAIN AST | 显示 SQL 的语法解析树(调试用) |
📦 三、详解四种 EXPLAIN 模式
1. EXPLAIN —— 执行计划(Execution Plan)
显示查询的逻辑执行树,每行代表一个执行步骤。
示例
EXPLAIN
SELECT user_id, COUNT(*)
FROM user_log
WHERE event_date = '2024-04-01'
GROUP BY user_id;
输出示例
Expression ((Projection + Before ORDER BY))
Aggregating
Filter (WHERE)
Expression (Before WHERE)
SettingQuotaAndLimits (Set limits and quota after reading from storage)
ReadFromStorage (default.user_log)
解读:
- ReadFromStorage:从
user_log表读取数据 - Expression (Before WHERE):准备 WHERE 条件
- Filter:应用
event_date = '2024-04-01'过滤 - Aggregating:执行
GROUP BY user_id - Expression (Projection):输出
user_id, COUNT(*)
✅ 用于理解查询的逻辑执行顺序。
2. EXPLAIN PIPELINE —— 执行流水线(关键性能分析工具)
显示查询的物理执行流水线,包括:
- 线程数
- 数据块大小
- 并行度
- 操作类型(如过滤、聚合)
示例
EXPLAIN PIPELINE
SELECT COUNT(*) FROM user_log WHERE event_date = '2024-04-01';
输出示例
Header: Count(UInt64) UInt64
MaxThreads
Expression
Aggregating
Filter
Expression
SettingQuotaAndLimits
ReadFromStorage (default.user_log) → Thread 0
→ Thread 1
→ Thread 2
→ Thread 3
关键信息:
MaxThreads:最大并行线程数(通常 = CPU 核心数)ReadFromStorage被分到 4 个线程 → 并行读取- 数据在多个线程中流动,形成流水线
✅ 用于分析:
- 是否充分利用多核
- 哪个阶段是瓶颈(如 Aggregating 单线程)
- 数据块大小(可通过
EXPLAIN PIPELINE format=pretty查看详细)
3. EXPLAIN ESTIMATE —— 数据扫描估算
显示查询将扫描多少行、多少分区,用于评估查询代价。
示例
EXPLAIN ESTIMATE
SELECT * FROM user_log WHERE event_date = '2024-04-01';
输出示例
rows: 1000000
bytes: 209715200
parts: 3
columns: 4
解读:
rows: 预计扫描 100 万行bytes: 预计读取 200MB 数据(未压缩)parts: 涉及 3 个数据片段(Part)columns: 读取 4 列
✅ 用于判断:
- 是否走了分区裁剪(
parts少 → 好)- 是否扫描过多数据(
rows大 → 考虑加索引或分区)
4. EXPLAIN AST —— 抽象语法树(高级调试)
显示 SQL 的语法解析树,用于调试复杂查询或理解 ClickHouse 内部如何解析 SQL。
示例
EXPLAIN AST SELECT 1 + 2;
输出示例
SelectWithUnionQuery
ExpressionList
Function
Identifier plus
ExpressionList
Literal UInt64(1)
Literal UInt64(2)
🛠️ 用途:
- 开发者调试
- 理解函数重写、常量折叠等优化
🎯 四、EXPLAIN 实战:如何分析慢查询?
场景:查询慢,怀疑未走索引
EXPLAIN
SELECT user_id, action
FROM user_log
WHERE city = 'Beijing'; -- city 不在 ORDER BY 中
分析输出:
Filter (WHERE)
ReadFromStorage (user_log)
- 没有
IndexCondition→ 未使用稀疏索引 - 全表扫描
优化建议:
- 将
city加入ORDER BY前缀 - 或使用
PARTITION BY city
场景:聚合性能差
EXPLAIN PIPELINE
SELECT user_id, COUNT(*) FROM user_log GROUP BY user_id;
输出发现:
Aggregating只有 1 个线程- 其他阶段多线程
原因:
GROUP BY在单线程汇总(默认)
优化建议:
- 启用
aggregation_memory_efficient_merge_threads提高合并并行度 - 或使用
Distributed表让每个分片先聚合
🛠️ 五、结合系统表进行性能分析
1. 查看最近查询(system.query_log)
SELECT
query,
query_duration_ms,
read_rows,
read_bytes,
result_rows
FROM system.query_log
WHERE event_date = today() AND query LIKE '%user_log%'
ORDER BY query_duration_ms DESC
LIMIT 10;
✅ 定位慢查询。
2. 查看数据部分(system.parts)
SELECT
name,
rows,
bytes_on_disk,
part_type
FROM system.parts
WHERE table = 'user_log';
✅ 判断数据是否合并良好。
✅ 六、EXPLAIN 使用最佳实践
| 场景 | 推荐 EXPLAIN 模式 |
|---|---|
| 理解执行顺序 | EXPLAIN |
| 分析并行度、瓶颈 | EXPLAIN PIPELINE |
| 评估扫描代价 | EXPLAIN ESTIMATE |
| 调试复杂 SQL | EXPLAIN AST |
优化建议
- 优先使用
EXPLAIN PIPELINE和ESTIMATE进行性能分析 - 关注
ReadFromStorage的线程数 → 是否并行读取 - 检查
Filter是否走了索引 → 减少扫描 - 避免大表全表扫描 → 使用分区 + 主键过滤
- 聚合阶段可并行化 → 合理设置
max_threads,aggregation_memory_efficient_merge_threads
📊 七、总结:EXPLAIN 各模式用途对比
| 模式 | 输出内容 | 适用场景 |
|---|---|---|
EXPLAIN | 逻辑执行树 | 理解查询流程 |
EXPLAIN PIPELINE | 物理流水线、线程、块 | 性能瓶颈分析 |
EXPLAIN ESTIMATE | 扫描行数、分区数、字节数 | 查询代价评估 |
EXPLAIN AST | SQL 语法树 | 高级调试 |
🎯 八、总结:EXPLAIN 的核心价值
EXPLAIN是 ClickHouse 的“查询透视镜”:
- 它让你看到 ClickHouse 内部如何执行 SQL
- 它帮你识别全表扫描、低并行、大聚合等性能瓶颈
- 它是优化索引、分区、表引擎设计的依据
4万+

被折叠的 条评论
为什么被折叠?



