EXPLAIN 类型
AST— 抽象语法树。SYNTAX— 经 AST 层级优化后的查询文本。QUERY TREE— 经查询树层级优化后的查询树。PLAN— 查询执行计划。PIPELINE— 查询执行流水线。
EXPLAIN AST
SELECT。
设置:
graph– 以 DOT 图描述语言定义的图形式输出 AST。默认值:0。
EXPLAIN SYNTAX
oneline– 以单行形式输出查询。默认值:0。run_query_tree_passes– 在转储查询树之前运行查询树处理阶段。默认值:0。query_tree_passes– 如果设置了run_query_tree_passes,则指定要运行的处理阶段数量。若未指定query_tree_passes,则会运行所有处理阶段。
Query
Response
run_query_tree_passes 时:
Query
Response
EXPLAIN QUERY TREE
run_passes— 在转储查询树之前运行所有查询树处理阶段。默认值:1。dump_passes— 在转储查询树之前,先转储已使用处理阶段的信息。默认值:0。passes— 指定要运行的处理阶段数量。如果设置为-1,则运行所有处理阶段。默认值:-1。dump_tree— 显示查询树。默认值:1。dump_ast— 显示根据查询树生成的查询 AST。默认值:0。
EXPLAIN PLAN
optimize— 控制在显示查询计划之前是否应用查询计划优化。默认值:1。header— 打印步骤的输出请求头。默认值:0。description— 打印步骤说明。默认值:1。indexes— 显示使用到的索引、每个已应用索引过滤掉的 parts 数量,以及过滤掉的粒度数量。默认值:0。支持 MergeTree 表。从 ClickHouse >= v25.9 开始,此语句只有在配合SETTINGS use_query_condition_cache = 0, use_skip_indexes_on_data_read = 0使用时,才会显示合理的输出。projections— 显示所有已分析的投影,以及它们基于投影主键条件对 part 级过滤的影响。对于每个投影,此部分都会包含统计信息,例如通过投影主键评估的 parts、行、标记和范围数量。它还会显示由于这种过滤而跳过了多少 data parts,而无需实际从投影本身读取数据。某个投影是否实际用于读取,还是仅用于过滤分析,可通过description字段判断。默认值:0。支持 MergeTree 表。actions— 打印步骤操作的详细信息。默认值:1。sorting— 为每个生成有序输出的计划步骤打印排序说明。默认值:0。keep_logical_steps— 对 joins 保留逻辑计划步骤,而不是将其转换为物理 join 实现。默认值:0。json— 以 JSON 格式将查询计划步骤打印为一行。默认值:0。建议使用 TabSeparatedRaw (TSVRaw) 格式,以避免不必要的转义。input_headers— 打印步骤的输入请求头。默认值:0。通常仅对开发者调试输入输出请求头不匹配相关问题时有用。column_structure— 除列名和类型外,还会打印请求头中列的结构。默认值:0。通常仅对开发者调试输入输出请求头不匹配相关问题时有用。distributed— 显示在远程节点上为分布式表或并行副本执行的查询计划。不支持与json一起使用。默认值:0。compact— 启用后,会在计划中隐藏表达式步骤以及详细操作信息 (输入、函数、别名和输出位置) 。仅在actions = 1时生效。默认值:1。pretty— 使用线框字符 (├──、└──、│) 而不是缩进来打印计划树,以便更直观地展示层级结构。还会以内联方式格式化 join 步骤属性。默认值:1。
默认情况下,
explain_query_plan_default = 'pretty',因此 actions、compact 和 pretty 都会初始化为 1,并且计划会以紧凑、美观且带操作注释的形式呈现。在 EXPLAIN 语句中显式指定这些选项中的任意一个 (例如 EXPLAIN actions = 0, compact = 0, pretty = 0 SELECT ...) 始终会覆盖默认值。在 ClickHouse 26.7 之前,actions、compact 和 pretty 的默认值为 0。你仍然可以通过将 explain_query_plan_default = 'legacy' (全局设置或在每个查询的 SETTINGS 中设置) ,或将 compatibility 设置为任何早于 26.7 的版本,来获得该输出。即使设置了 explain_query_plan_default = 'pretty',json 和 distributed 选项也不会启用 pretty 的默认值 (actions、compact 和 pretty) 。若要在其输出中包含操作详情,请手动设置 actions = 1。不支持步骤和查询成本估算。
json = 1 时,查询计划会以 JSON 格式表示。每个节点都是一个字典,并且始终包含 Node Type、Node Id 和 Plans 键。Node Type 是表示步骤名称的字符串,Node Id 是唯一的步骤标识符 (步骤名称加上数字后缀,例如 Union_10) 。Plans 是一个包含子步骤描述的数组。根据节点类型和设置,还可能会添加其他可选键。
示例:
description = 1 时,Description 键会添加到该步骤中:
header = 1 时,Header 键会以列数组的形式添加到该步骤中。
示例:
indexes = 1 时,会添加 Indexes 键。它包含一个由已使用索引组成的数组。每个索引都以 JSON 格式描述,包含 Type 键 (其值为字符串 Partition Min-Max、Partition、Statistics、PrimaryKey 或 Skip) 以及以下可选键:
Name— 索引名称 (目前仅用于Skip索引) 。Keys— 该索引使用的列数组。Condition— 使用的条件。Description— 索引描述 (目前仅用于Skip索引) 。Parts— 应用该索引后/前的 parts 数量。Granules— 应用该索引后/前的粒度数量。Ranges— 应用该索引后的粒度范围数量。
projections = 1 时,将添加 Projections 键。它包含一个已分析的 projections 数组。每个 projection 以 JSON 格式描述,包含以下键:
Name— 投影名称。Condition— 使用的投影主键条件。Description— 关于投影如何使用的描述 (例如 part 级过滤) 。Selected Parts— 该投影选中的 parts 数量。Selected Marks— 选中的标记数量。Selected Ranges— 选中的范围数量。Selected Rows— 选中行数。Filtered Parts— 由于 part 级过滤而跳过的 parts 数量。
actions = 1 时,添加的键取决于步骤类型。
示例:
compact = 0 且 actions = 1 时,可以看到 Expression 步骤以及表达式的详细信息:
distributed = 1 时,输出不仅包含本地查询计划,还包含将在远程节点上执行的查询计划。这对于分析和调试分布式查询非常有用。
distributed 仅以 legacy (非 pretty) 格式呈现,因为 pretty 输出不会将远程分片的计划整合到计划树中。因此,启用 distributed 会自动禁用 pretty 的默认选项 (actions、compact 和 pretty) ,无论 explain_query_plan_default 如何设置。你仍然可以手动设置 actions=1。distributed 选项也不支持与 json 一起使用。pretty = 1 时,计划树将以线条字符代替缩进的方式展示,并为关键步骤显示额外信息:
- 查询输出列 会显示在计划顶部。
- 过滤器、聚合键、排序描述和窗口函数中的 表达式 会以人类可读的类 SQL 记法显示 (例如,使用
a + 1 > 5而不是greater(plus(a, 1), 5)) 。为便于理解,内部列标识符前缀 (例如__table1.) 会被移除。 - 源步骤 (例如
ReadFromMergeTree) 会显示其输出列。 - 过滤步骤 会以 SQL 记法显示过滤条件。存在运行时 join 过滤器时,它们会单独显示。
- 聚合步骤 会显示键以及聚合函数及其参数 (例如
sum(c)、count()) 。 - 来自元组字面量的 IN 集合 会显示其值 (大型集合会被截断) ,基于子查询的集合会标记为
subquery1、subquery2等,而来自Setengine 表的集合会显示表名。 - Join 步骤 会使用数学记法显示 join 关系、预估结果行数, 以及哪些输出列来自左侧或右侧。以下符号用于 表示不同的 JOIN types:
例如,
t1 ⟕ t2 表示表 t1 与 t2 之间的左连接。
表名后方括号中的数字 (例如 t1[100]) 表示预估行数,
前提是表统计信息可用。
pretty 选项与 compact = 1 搭配使用效果很好,它会隐藏 Expression 步骤和详细的动作信息,使执行计划更易于阅读。
一个详细的 JOIN 示例:
EXPLAIN PIPELINE
header— 为每个输出端口打印请求头。默认值:0。graph— 打印以 DOT 图描述语言表示的图。默认值:0。compact— 如果启用了graph设置,则以紧凑模式打印图。默认值:1。compact_repeated_processor_chains— 在文本输出中,通过显示一份事件链副本及其重复次数,将相邻的重复处理器事件链进行紧凑表示。当同一事件链多次出现时 (例如在 joins 中) ,这可以让并行管道更易于阅读。它不会影响图输出。默认值:0。
compact=0 且 graph=1 时,处理器名称会包含一个额外的后缀,用于标明处理器的唯一标识符。
示例:
EXPLAIN ESTIMATE
Query
Query
Response
EXPLAIN WHATIF
SELECT 查询的潜在收益。使用 CREATE HYPOTHETICAL INDEX 定义一个或多个候选项,然后运行 EXPLAIN WHATIF SELECT ...,即可查看每个候选项的以下信息:是否适用、预估读取的标记数、预估字节数以及跳过比率。
语法
empirical—1(默认值) 会在内存中对经过基线剪枝的粒度运行索引,以测量跳过比例 (上限) 。0则会跳过该路径。无论哪种情况,如果 empirical 未产生结果 (已禁用,或索引无法在内存中求值) ,估算器都会回退到列统计信息;如果两者都不可用,则最终回退到仅包含适用性的摘要。
source— 估算的来源。empirical:在内存中基于经过基线剪枝后的粒度构建索引,并统计该索引原本可以跳过的粒度数。这是一个上界——请参阅CREATE HYPOTHETICAL INDEX中的限制。statistical:根据列统计信息推导得出。当经验估算被禁用 (empirical = 0) ,或经验估算无法得出结果,且相关列已定义列统计信息时使用。applicability_only:该索引适用于该谓词,但经验估算和统计估算都未得出结果 (例如empirical = 0且未定义列统计信息) 。作为保守上界,会报告skip_ratio: 0.0%。
sampled_parts/sampled_marks—<baseline-pruned> / <total in the table>。显示在经过 PK、分区和现有索引剪枝后,表中有多少比例的数据被保留下来,即假设索引的输入。est_bytes— 读取字节数的估算值,由表的平均行大小推导而来,因此只是近似值,并会随存储和压缩情况而变化。只有当查询读取行时才会显示 baseline 行;只有在已知 baseline 字节估算值时,才会显示各候选项对应的行。
WHATIF 与 SELECT 之间——没有 SETTINGS 关键字 (这与其他 EXPLAIN 变体接受选项的方式一致) 。
如果该表没有定义任何假设索引,EXPLAIN WHATIF 会报告 status: not_applicable,并提示你创建一个。
经验估算示例
minmax,可将 100 个标记裁减到只剩 1 个——skip_ratio: 99.0%。 (est_bytes 是根据平均行大小估算得出的,因此具体数值会有所不同。)
统计示例
列统计信息默认处于关闭状态。要触发 statistical 路径,请先在相关列上定义统计信息,然后等待物化变更完成:
b < 10 的列统计信息选择性 (10000 行中约 10 行) ,并以 skip_ratio 上界的形式给出。不存在 sampled_parts / sampled_marks——未读取任何数据。
如果这两种路径都不可用 (例如 empirical = 0 且未定义列统计信息) ,估算器会报告 source: applicability_only,以及保守的 skip_ratio: 0.0%。
EXPLAIN TABLE OVERRIDE
Query
Query
Response
验证并不完整,因此查询成功也不能保证该覆盖不会导致问题。