You need to enable JavaScript to run this app.
导航
执行计划 EXPLAIN
最近更新时间:2025.07.08 12:45:51首次发布时间:2024.06.18 11:33:16
复制全文
我的收藏
有用
有用
无用
无用

ByteHouse 支持通过 EXPLAIN 语句为 SQL 语句生成对应的执行计划,帮助您了解 ByteHouse 如何执行查询,便于您针对性优化 SQL 语句。本文以 TPCH-Q1 中的 SQL 为例,演示了如何使用不同类型的 EXPLAIN 语句。

功能概述

在 ByteHouse 中,优化器(Query Optimizer)通过规则优化(Rule-Based Optimization,RBO)、代价优化(Cost-Based Optimization,CBO)、原生分布式计划协同、及高阶能力(动态过滤下推/物化视图改写),实现全链路查询优化。开启优化器后,执行 EXPLAIN 语句将为 SQL 语句生成对应的执行计划,展示执行计划的详细信息,并生成更高效的执行计划,可帮助开发人员快速定位 SQL 性能瓶颈,可针对性优化索引设计、表达式复杂度或分布式执行策略,确保以最小资源开销快速返回结果。
ByteHouse 当前支持了以下类型的 EXPLAIN 语句:

类型

定义

EXPLAIN

用于展示逻辑执行计划。

EXPLAIN DISTRIBUTED

用于展示分布式执行计划。

EXPLAIN ANALYZE

用于展示带有运行时信息的执行计划,可细分为以下类型:

EXPLAIN AST

转储查询的抽象语法树(AST),支持所有类型的查询,不仅仅是 SELECT

EXPLAIN SYNTAX

返回经过语法优化后的查询。

EXPLAIN METADATA

该语句用于展示 SQL Analyzer 阶段解析的一些信息,解析的信息主要包括,库名,表明,列名,函数名,settings 等信息。

语法
EXPLAIN [DISTRIBUTED | ANALYZE | AST | SYNTAX | METADATA ] [setting = value, ...]
    [
      SELECT ... |
      tableFunction(...) [COLUMNS (...)] [ORDER BY ...] [PARTITION BY ...] [PRIMARY KEY] [SAMPLE BY ...] [TTL ...]
    ]
    [FORMAT ...]

参数说明

参数

是否必填

说明

DISTRIBUTED

ANALYZE

AST

setting = value

设置自定义查询执行参数。
例如,您可以使用 json 设置是否以 JSON 格式打印计划,设置为 1 表示打印 JSON 格式的计划,设置为 0 表示不打印,该参数设置后的效果与设置 FORMAT 相同。示例:json = 1

SELECT

二选一

与 tableFunction(...) 二选一。设置为需要分析的 SELECT 查询语句。

tableFunction(...)

二选一

与 SELECT 二选一。设置为需要分析的表函数。

COLUMNS (...)

定义表函数需要返回的列名和类型。

ORDER BY

定义表函数的排序键。

PARTITION BY

定义表函数的数据分区规则。

PRIMARY KEY

设置表函数的索引主键。

SAMPLE BY

声明表函数的采样表达式。

TTL

配置表函数的数据过期策略。

FORMAT

定义将结果转换成指定输出格式。

示例

EXPLAIN json=0
SELECT
    l_returnflag,
    l_linestatus,
    sum(l_quantity) AS sum_qty,
    sum(l_extendedprice) AS sum_base_price,
    sum(l_extendedprice * (1 - l_discount)) AS sum_disc_price,
    sum((l_extendedprice * (1 - l_discount)) * (1 + l_tax)) AS sum_charge,
    avg(l_quantity) AS avg_qty,
    avg(l_extendedprice) AS avg_price,
    avg(l_discount) AS avg_disc,
    count(*) AS count_order
FROM lineitem
WHERE l_shipdate <= (toDate('1998-12-01') - toIntervalDay('90'))
GROUP BY
    l_returnflag,
    l_linestatus
ORDER BY
    l_returnflag ASC,
    l_linestatus ASC

输出结果
Image

EXPLAIN 类型

EXPLAIN DISTRIBUTED

该语句用于展示分布式执行计划。

语法

EXPLAIN DISTRIBUTED <SQL>;

示例

EXPLAIN DISTRIBUTED
SELECT
    l_returnflag,
    l_linestatus,
    sum(l_quantity) AS sum_qty,
    sum(l_extendedprice) AS sum_base_price,
    sum(l_extendedprice * (1 - l_discount)) AS sum_disc_price,
    sum((l_extendedprice * (1 - l_discount)) * (1 + l_tax)) AS sum_charge,
    avg(l_quantity) AS avg_qty,
    avg(l_extendedprice) AS avg_price,
    avg(l_discount) AS avg_disc,
    count(*) AS count_order
FROM lineitem
WHERE l_shipdate <= (toDate('1998-12-01') - toIntervalDay('90'))
GROUP BY
    l_returnflag,
    l_linestatus
ORDER BY
    l_returnflag ASC,
    l_linestatus ASC 

输出结果
Image

EXPLAIN ANALYZE

EXPLAIN ANALYZE 用于展示带有运行时信息的执行计划,也支持通过 EXPLAIN ANALYZE DISTRIBUTED 展示带有运行时信息的分布式执行计划。
这类语句支持的通用 setting 参数如下:

参数

是否必填

说明

json

设置是否以 JSON 格式打印计划,默认值为 0,表示不以 JSON 格式输出,设置为 1 表示打印 JSON 格式的计划。示例:json = 1

stats

设置是否输出统计信息行数和 cost,默认值为 1,表示输出,设置为 0 表示不输出。示例:stats = 1

profile

设置是否输出执行时 profiles,默认值为 1,表示输出,设置为 0 表示不输出。示例:profile = 1

verbose

设置是否输出输出逻辑计划 node 详细内容,默认值为 1,表示输出,设置为 0 表示不输出。示例:verbose = 1

indexes

设置是否打印索引使用情况,设置为 1 表示打印,设置为 0 表示不打印。示例:indexes = 1

segment_id

设置 segment id,可在打印分布式计划时指定打印具体 segment 内容。

segment_profile

设置是否在打印分布式计划打印 segment 耗时,设置为 1 表示打印,设置为 0 表示不打印。示例:segment_profile = 1

EXPLAIN ANALYZE

该语句用于展示带有运行时信息的执行计划。具体字段说明请参见 Explain Analyze字段说明

语法
EXPLAIN ANALYZE <SQL>;

参数说明

除了通用参数外,EXPLAIN ANALYZE 还支持设置以下 setting 参数:

  • processor_profile_events:设置是否输出执行计划执行时每个PlanNode上的ProfileEvents metrics。设置为 1 时,系统将输出相关内容并按节点做聚合,设置为 0 时,表示不输出。示例:processor_profile_events = 1

示例
EXPLAIN ANALYZE
SELECT
    l_returnflag,
    l_linestatus,
    sum(l_quantity) AS sum_qty,
    sum(l_extendedprice) AS sum_base_price,
    sum(l_extendedprice * (1 - l_discount)) AS sum_disc_price,
    sum((l_extendedprice * (1 - l_discount)) * (1 + l_tax)) AS sum_charge,
    avg(l_quantity) AS avg_qty,
    avg(l_extendedprice) AS avg_price,
    avg(l_discount) AS avg_disc,
    count(*) AS count_order
FROM lineitem
WHERE l_shipdate <= (toDate('1998-12-01') - toIntervalDay('90'))
GROUP BY
    l_returnflag,
    l_linestatus
ORDER BY
    l_returnflag ASC,
    l_linestatus ASC

输出结果
Image

EXPLAIN ANALYZE DISTRIBUTED

该语句用于展示带有运行时信息的分布式执行计划,具体字段说明请参见 Explain Analyze字段说明

语法
EXPLAIN ANALYZE DISTRIBUTED <SQL>;

参数说明

除了通用参数外,EXPLAIN ANALYZE DISTRIBUTED 还支持设置以下 setting 参数:

  • processor_profile_events:设置是否输出执行计划执行时每个PlanNode上的ProfileEvents metrics。设置为 1 时,系统将输出相关内容并按节点做聚合,设置为 0 时,表示不输出。示例:processor_profile_events = 1
  • profile_events_list:可用于输出分布式计划执行时的 ProfileEvents,默认是聚合的。如需分别显示每个节点的 ProfileEvents,可设置 aggregate_profiles=0。示例:profile_events_list='QueryAnalyzerTime',如果有多个参数值,可使用逗号(,)分隔。
  • aggregate_profiles:设置 aggregate_profiles = 1,可打印每个 worker 聚合后的 profile,设置 aggregate_profiles = 0,系统将分别打印出每个 worker 的 profiles。

示例
EXPLAIN ANALYZE DISTRIBUTED
SELECT
    l_returnflag,
    l_linestatus,
    sum(l_quantity) AS sum_qty,
    sum(l_extendedprice) AS sum_base_price,
    sum(l_extendedprice * (1 - l_discount)) AS sum_disc_price,
    sum((l_extendedprice * (1 - l_discount)) * (1 + l_tax)) AS sum_charge,
    avg(l_quantity) AS avg_qty,
    avg(l_extendedprice) AS avg_price,
    avg(l_discount) AS avg_disc,
    count(*) AS count_order
FROM lineitem
WHERE l_shipdate <= (toDate('1998-12-01') - toIntervalDay('90'))
GROUP BY
    l_returnflag,
    l_linestatus
ORDER BY
    l_returnflag ASC,
    l_linestatus ASC

输出结果
Image

EXPLAIN AST

转储查询的抽象语法树(AST),支持所有类型的查询,不仅仅是 SELECT

语法

EXPLAIN AST <SQL>;

示例

EXPLAIN AST
SELECT
    l_returnflag,
    l_linestatus,
    sum(l_quantity) AS sum_qty,
    sum(l_extendedprice) AS sum_base_price,
    sum(l_extendedprice * (1 - l_discount)) AS sum_disc_price,
    sum((l_extendedprice * (1 - l_discount)) * (1 + l_tax)) AS sum_charge,
    avg(l_quantity) AS avg_qty,
    avg(l_extendedprice) AS avg_price,
    avg(l_discount) AS avg_disc,
    count(*) AS count_order
FROM lineitem
WHERE l_shipdate <= (toDate('1998-12-01') - toIntervalDay('90'))
GROUP BY
    l_returnflag,
    l_linestatus
ORDER BY
    l_returnflag ASC,
    l_linestatus ASC

输出结果

Image

EXPLAIN SYNTAX

返回经过语法优化后的查询。

语法

EXPLAIN SYNTAX <SQL>;

示例

EXPLAIN SYNTAX
SELECT
    l_returnflag,
    l_linestatus,
    sum(l_quantity) AS sum_qty,
    sum(l_extendedprice) AS sum_base_price,
    sum(l_extendedprice * (1 - l_discount)) AS sum_disc_price,
    sum((l_extendedprice * (1 - l_discount)) * (1 + l_tax)) AS sum_charge,
    avg(l_quantity) AS avg_qty,
    avg(l_extendedprice) AS avg_price,
    avg(l_discount) AS avg_disc,
    count(*) AS count_order
FROM lineitem
WHERE l_shipdate <= (toDate('1998-12-01') - toIntervalDay('90'))
GROUP BY
    l_returnflag,
    l_linestatus
ORDER BY
    l_returnflag ASC,
    l_linestatus ASC

输出结果
Image

EXPLAIN METADATA

该语句用于展示 SQL Analyzer 阶段解析的一些信息,解析的信息主要包括,库名,表明,列名,函数名,settings 等信息。

使用限制

  • 仅在 EXPLAIN METADATA <SQL> 形式下使用;
  • 只对 SELECT 和 INSERT SELECT 的查询生效。

语法

EXPLAIN METADATA <SQL>;

参数说明

EXPLAIN METADATA 支持设置以下 setting 参数:

  • format_json:设置 format_json = 1 表示输出内容是 JSON 格式。
  • lineage:设置是否输出 SQL 血缘关系信息,设置为 1 表示展示,设置为 0 表示不展示。示例:lineage = 1

示例 1

explain metadata select t1.a, t2.b from metadata t1 join metadata2 t2 on t1.a=t2.a settings enable_optimizer=1;

输出结果
Image
其中的字段说明如下:

  • tables:查询中涉及的表,array 类型。
  • databases:tables 字段中表对应的数据库,array(String) 类型。
  • column_lists:tables 字段中表在当前查询中使用到的列,array(array(String)) 类型。
  • used_function_names:查询中用到的函数名,array(String) 类型。
  • settings:查询中生效的 settings 名,map(string, string) 类型。
  • insert_info:insert的库名,表名和列名,array(array(String)) 类型。

示例 2

EXPLAIN METADATA format_json = 1, lineage = 1
WITH t3 AS
    (
        SELECT
            count() AS a,
            sum(b) AS b
        FROM cache2
        GROUP BY c
    )
SELECT
    a,
    b
FROM
(
    (
        SELECT
            t3.b AS a,
            t2.b AS b
        FROM cache AS t2
        INNER JOIN t3 ON t2.a = t3.a
    )
    UNION ALL
    (
        SELECT 
            *
        FROM t3
    )
) AS t1
WHERE t1.a = 1
SETTINGS enable_optimizer = 1
FORMAT TabSeparatedRaw

输出结果

{
 "UsedTablesInfo" : [
  {
   "Database" : "test",
   "Table" : "cache",
   "Columns" : [
    "a",
    "b"
   ]
  },
  {
   "Database" : "test",
   "Table" : "cache2",
   "Columns" : [
    "b",
    "c"
   ]
  }
 ],
 "UsedFunctions" : [
  "count",
  "equals",
  "sum"
 ],
 "UsedSettings" : {
  "enable_optimizer" : "1"
 },
 "InsertInfo" : {
 },
 "FunctionsInfo" : [

 ],
 "LineageInfo" : {
  "TableSources" : [
   {
    "Database" : "test",
    "Table" : "cache2",
    "Columns" : [
     {
      "Id" : 3,
      "Name" : "b"
     },
     {
      "Id" : 2,
      "Name" : "c"
     }
    ]
   },
   {
    "Database" : "test",
    "Table" : "cache",
    "Columns" : [
     {
      "Id" : 1,
      "Name" : "a"
     },
     {
      "Id" : 0,
      "Name" : "b"
     }
    ]
   }
  ],
  "ExpressionSources" : [
   {
    "Sources" : [
     {
      "Database" : "test",
      "Table" : "cache2"
     }
    ],
    "Expression" : [
     {
      "Id" : 4,
      "Name" : "expr#count()"
     }
    ]
   }
  ],
  "OutputLineageInfo" : [
   {
    "Name" : "b",
    "SourceIds" : [
     3,
     0
    ]
   },
   {
    "Name" : "a",
    "SourceIds" : [
     4,
     3
    ]
   }
  ],
  "InsertLinageInfo" : {
  }
 }
}

其中字段说明如下:

  • TableSources:查询中所有的表对应的原始列信息,所有的列(column)对应一个 ID。
  • ExpressionSources:查询中由表达式、常量、无法找到对应原始列信息的聚合函数信息,每个表达式也对应一个 ID。其中 Sources 字段包含了生成该表达式涉及的表信息。
  • OutputLineageInfo:查询所有输出的字段名和对应的原始列或表达式(expression)的 ID,其中 Name 为输出的字段名,SourceIds 为对应的列或表达式的 IDs。
  • InsertLinageInfo:insert select 插入语句中插入的表和列信息和对应 select 子句输出字段名的对应关系。InsertColumnName 为插入语句中对应的列名,InputName 为对应 OutputLineageInfo 中输出字段名。