ClickHouse EXPLAIN 完全实战指南:AST / SYNTAX / QUERY TREE / PLAN / PIPELINE 一文搞懂
摘要ClickHouse 提供 5 种 EXPLAIN 类型分别对应查询编译的不同阶段。很多同学只会EXPLAIN PLAN遇到「SQL 被改写了」「优化器做了什么」就无从下手。本文按可上手操作的方式逐类型讲解用法、输出解读和排查场景并附一套慢查询分析流程。配套工具执行计划可视化 AI 调优 → https://ch.charunion.com关键词ClickHouse、EXPLAIN、AST、SYNTAX、QUERY TREE、PLAN、PIPELINE、慢查询、SQL 优化一、EXPLAIN 是什么先建立整体认知在 ClickHouse 里EXPLAIN不是「估算成本」那么简单和 Oracle/MySQL 的 EXPLAIN 习惯不完全一样它更像一条查询编译透视链原始 SQL ↓ 解析 AST抽象语法树 ↓ AST 级优化 SYNTAX优化后 SQL 文本 ↓ Query Tree 级优化 QUERY TREE逻辑查询树 ↓ 物理计划生成 PLAN执行计划 ↓ 流水线展开 PIPELINE执行流水线一句话记忆类型回答的问题ASTSQL 被解析成了什么结构SYNTAX优化器在语法层把 SQL 改成了什么样QUERY TREE逻辑算子树长什么样PLAN最终怎么读表、怎么聚合最常用PIPELINE底层 Processor 怎么串起来最深二、准备统一测试 SQL 和表结构下文所有示例共用一张表复制即可跑。2.1 建表CREATEDATABASEIFNOTEXISTSdemo;CREATETABLEIFNOTEXISTSdemo.events(event_dateDate,event_timeDateTime,user_id UInt64,event_type String,properties String)ENGINEMergeTree()PARTITIONBYtoYYYYMM(event_date)ORDERBY(event_date,event_time,user_id);2.2 测试 SQLSELECTevent_type,count()AScnt,uniq(user_id)ASuvFROMdemo.eventsWHEREevent_datetoday()-7GROUPBYevent_typeORDERBYcntDESCLIMIT10;2.3 基本语法格式EXPLAIN[AST|SYNTAX|QUERY TREE|PLAN|PIPELINE][选项]你的SELECT语句在clickhouse-client或 HTTP 接口8123均可执行。多行 SQL 时建议去掉末尾分号或整体包在子查询里。三、五种 EXPLAIN 类型详解附操作命令3.1 AST — 抽象语法树Abstract Syntax Tree作用查看 SQL解析后的语法树结构对应编译最早期。什么时候用怀疑 SQL 写法有歧义想看 ClickHouse 怎么「理解」你的语句调试宏、复杂嵌套子查询的解析结果语法报错时定位解析阶段问题命令EXPLAINASTSELECTevent_type,count()AScnt,uniq(user_id)ASuvFROMdemo.eventsWHEREevent_datetoday()-7GROUPBYevent_typeORDERBYcntDESCLIMIT10;输出特点树形结构节点类型如SelectQuery、TablesInSelectQuery、Identifier、Function等能看到 SELECT 列表、FROM、WHERE、GROUP BY、ORDER BY 在语法树上的位置不涉及物理执行、不涉及读多少行怎么读找到根节点SelectQuery向下看TablesInSelectQuery→ 确认表名、别名看ExpressionList→ 确认列和函数是否按预期解析局限AST 离「性能」还远不能用它判断慢不慢。3.2 SYNTAX — AST 级优化后的 SQL 文本作用展示经过AST 层优化之后的查询文本。什么时候用发现「我写的 SQL」和「实际执行的 SQL」不一样排查常量折叠、谓词下推前的语法改写对比改写前后理解优化器在语法层做了什么命令EXPLAINSYNTAXSELECTevent_type,count()AScnt,uniq(user_id)ASuvFROMdemo.eventsWHEREevent_datetoday()-7GROUPBYevent_typeORDERBYcntDESCLIMIT10;输出特点通常返回一段可读的 SQL 文本不是树可能合并了部分表达式、规范了函数写法仍属于较「逻辑」的层面不是执行计划实战技巧把EXPLAIN SYNTAX的输出复制出来和原始 SQL 做 diff日期条件是否被折叠成具体值别名、函数是否被替换子查询是否被展开或改写示例场景-- 原始SELECTcount()FROMdemo.eventsWHEREevent_datetoday()-7;-- EXPLAIN SYNTAX 可能显示类似具体因版本而异-- SELECT count() FROM demo.events WHERE event_date toDate(2026-06-23)这说明today() - 7在语法优化阶段已被求值。3.3 QUERY TREE — Query Tree 级优化后的查询树作用展示Query Tree 层优化之后的逻辑查询树介于「SQL 文本」和「物理计划」之间。什么时候用想看 JOIN、子查询、聚合在逻辑层如何组织PLAN 看不懂时回退一层看逻辑结构分析 CTE、UNION、子查询合并等行为命令EXPLAINQUERY TREESELECTevent_type,count()AScnt,uniq(user_id)ASuvFROMdemo.eventsWHEREevent_datetoday()-7GROUPBYevent_typeORDERBYcntDESCLIMIT10;输出特点树形逻辑算子JOIN、FILTER、AGGREGATE、SORT、LIMIT等比 SYNTAX 更接近执行但还不是ReadFromMergeTree那种物理算子不同 ClickHouse 版本节点命名可能略有差异怎么读自顶向下最外层通常是 LIMIT / SORT中间层AGGREGATE聚合、FILTER过滤底层表扫描相关的逻辑节点和 PLAN 的分工QUERY TREE逻辑上「先过滤还是先聚合」PLAN物理上「从哪张表、用什么方式读」3.4 PLAN — 查询执行计划最常用作用展示物理执行计划是日常慢查询分析的首选。什么时候用慢查询排查80% 的场景用这个就够看是否全表扫描、分区是否裁剪看聚合、排序、JOIN 发生在哪一层和system.query_log对照「计划 vs 实际」命令文本格式推荐入门EXPLAINPLANSELECTevent_type,count()AScnt,uniq(user_id)ASuvFROMdemo.eventsWHEREevent_datetoday()-7GROUPBYevent_typeORDERBYcntDESCLIMIT10;典型输出示意Expression (Project names) Limit (preliminary LIMIT (without OFFSET)) Sorting (Sorting for ORDER BY) Expression ((Before ORDER BY (Projection (WHERE (PREWHERE ...))))) Aggregating Expression (Before GROUP BY) Filter (WHERE) ReadFromMergeTree (demo.events)命令JSON 格式适合程序解析EXPLAINPLANjson1,description1SELECTevent_type,count()AScnt,uniq(user_id)ASuvFROMdemo.eventsWHEREevent_datetoday()-7GROUPBYevent_typeORDERBYcntDESCLIMIT10;重点看什么节点关注点ReadFromMergeTree读哪张表、预估/实际行数、是否命中分区Filter/PREWHERE过滤条件下推情况Aggregating聚合是否在大结果集上进行Sorting是否在内存中排序大量数据LimitLIMIT 是否下推、是否 preliminary实战口诀先找最底层的ReadFromMergeTree再往上数Filter→Aggregating→Sorting。如果Aggregating上面还有巨大的ReadFromMergeTree且行数很高优先怀疑条件没下推、分区没裁剪、ORDER BY 键不合理。配合 query_log-- 先真正执行一次SELECT...;-- 再查最近一次执行的指标SELECTquery_duration_ms,read_rows,read_bytes,memory_usage,queryFROMsystem.query_logWHEREtypeQueryFinishANDqueryLIKE%demo.events%ORDERBYevent_timeDESCLIMIT5;EXPLAIN 是计划query_log 是结果两者必须对照看。3.5 PIPELINE — 查询执行流水线作用展示查询的Pipeline 执行图细化到 Processor处理器级别比 PLAN 更底层。什么时候用PLAN 不够用想看多线程、流水线并行怎么组织排查特定算子实现、数据流端口Port连接深度性能调优、向 ClickHouse 社区报 Bug 时附材料命令EXPLAINPIPELINESELECTevent_type,count()AScnt,uniq(user_id)ASuvFROMdemo.eventsWHEREevent_datetoday()-7GROUPBYevent_typeORDERBYcntDESCLIMIT10;输出特点编号步骤(1)、(2)… 描述 Processor 链可能出现MergeTreeSelect、ExpressionTransform、AggregatingTransform等信息量大日常优化不建议从这里入手可选图形化输出部分版本支持EXPLAINPIPELINE graph1SELECT...;和 PLAN 的关系PLAN → 「做什么」读表、过滤、聚合、排序 PIPELINE → 「怎么做」Processor 如何串联、数据如何流动四、五种类型对比速查表类型编译阶段输出形态日常频率主要用途AST解析语法树★☆☆☆☆语法结构、解析调试SYNTAXAST 优化后SQL 文本★★☆☆☆看 SQL 被改写成什么样QUERY TREE逻辑优化后逻辑算子树★★★☆☆逻辑层 JOIN/聚合/子查询PLAN物理计划树 / JSON★★★★★慢查询分析主力PIPELINE流水线Processor 链★★☆☆☆深度调优、源码级排查五、推荐上手流程5 步排查慢查询假设有一条生产慢 SQL按这个顺序操作不容易走弯路。第 1 步EXPLAIN PLAN必做EXPLAINPLAN你的慢SQL;确认扫描节点、过滤位置、聚合/排序层级。第 2 步查 query_log必做SELECTevent_time,query_duration_ms,read_rows,read_bytes,memory_usage,tables,queryFROMsystem.query_logWHEREtypeQueryFinishANDquery_duration_ms1000ORDERBYevent_timeDESCLIMIT20;确认实际读了多少行、耗时多久。第 3 步结果和预期不符时 → EXPLAIN SYNTAX看 SQL 是否被改写条件是否被折叠或下推失败。第 4 步PLAN 逻辑看不懂时 → EXPLAIN QUERY TREE回退到逻辑层理清 JOIN / 子查询 / 聚合顺序。第 5 步仍无法定位 → EXPLAIN PIPELINE 或抓 profile仅在前四步不够时再下钻避免信息过载。日常优化PLAN query_log 占 90% 语法疑惑补 SYNTAX 结构复杂补 QUERY TREE 底层深挖PIPELINE六、三个常见实战案例案例 1条件没下推读行数爆炸现象read_rows上亿query_duration_ms很高。操作EXPLAINPLANSELECTcount()FROMdemo.eventsWHEREtoYYYYMM(event_date)202506;PLAN 里若看到大范围ReadFromMergeTreeFilter在扫描之后 → 分区/主键没用上。方向改写为event_date范围条件对齐PARTITION BY和ORDER BY。案例 2聚合前数据量过大现象Aggregating节点上方读取行数极高。操作EXPLAINPLANSELECTuser_id,count()FROMdemo.eventsGROUPBYuser_id;方向增加 PREWHERE / WHERE 缩小范围考虑物化视图预聚合检查GROUP BY基数是否过高案例 3ORDER BY 导致大量排序现象Sorting节点存在且read_rows大。操作EXPLAINPLANSELECT*FROMdemo.eventsORDERBYevent_typeLIMIT100;方向ORDER BY列不在排序键上时必然大排序评估是否可改写法或加投影/索引视版本而定七、命令行 vs 在线工具怎么选命令行clickhouse-client优点生产环境直接查、可脚本化缺点树形输出难读、多类型切换麻烦、要和 query_log 手动对照在线可视化工具如果经常要在团队里分享分析结果可以借助可视化工具减少手工整理。我近期做了一个ClickHouse EXPLAIN 可视化 AI 调优助手把上面几种 EXPLAIN 类型和慢查询分析流程做成了「可点击」的操作地址https://ch.charunion.com能帮你做什么功能说明五种 EXPLAIN 类型AST / SYNTAX / QUERY TREE / PLAN / PIPELINE 一键切换离线模式粘贴已有 EXPLAIN 结果无需连库连接模式直连 ClickHouse自动执行 EXPLAIN计划树可视化把 PLAN 输出解析成可折叠树形图query_log 关联扫描节点挂载真实 read_rows、耗时等指标AI 调优对话结合 SQL、DDL、执行计划追问优化建议推荐使用方式本地先用EXPLAIN PLAN跑一遍熟悉 raw 输出把 SQL EXPLAIN 结果粘贴到 https://ch.charunion.com 离线模式在「执行计划」「诊断」「AI 助手」Tab 里继续深挖测试环境可开连接模式自动拉 query_log访客可直接分析登录后可保存历史记录、使用 AI 助手。八、版本差异与注意事项不同 ClickHouse 版本EXPLAIN 节点名称和 JSON 字段可能略有不同以你集群版本为准。分布式表的 PLAN 会更复杂注意ReadFromRemote、Union等节点。EXPLAIN 不执行完整查询PLAN 模式但仍有解析和计划开销避免对超大 SQL 频繁执行。JSON PLAN适合程序消费人工阅读优先用文本 PLAN。生产环境若不能直连用离线模式把 EXPLAIN 结果复制到工具里分析即可。九、总结你想知道…用这个SQL 怎么被解析的EXPLAIN ASTSQL 被改写成啥了EXPLAIN SYNTAX逻辑算子怎么组织的EXPLAIN QUERY TREE怎么读表、怎么跑EXPLAIN PLAN⭐Processor 怎么流水线执行EXPLAIN PIPELINE日常口诀PLAN看计划query_log看结果对不上就查SYNTAX和QUERY TREE。如果你希望少在终端和文档之间来回切换可以直接用可视化工具辅助https://ch.charunion.com欢迎在评论区交流你遇到的 EXPLAIN 输出案例后续可以专门写一篇「PLAN 节点大全」。