执行 SQL 并查看执行计划

最近更新时间:2024-08-02 16:34:02

我的收藏
只读分析引擎兼容 MySQL 协议与语法。用户可通过 MySQL 客户端或开发语言中的 MySQL 连接器访问到只读分析引擎中执行 SQL 语句。
只读分析引擎是一个只读实例,故可执行的 SQL 语句主要为 SELECT 语句,无法执行 DML 和 DDL 语句。同时查询也严格受限于对象权限,若访问账户不拥有某一对象的 SELECT 权限,则亦无法进行此对象的查看。
在执行 SQL 时,可直接使用 MySQL 的语法进行语法编辑,然后到只读分析引擎中执行。但是时常也会遇到执行结果不及预期的情况,此时则可以通过 EXPLAIN 功能查看执行计划。

EXPLAIN 功能及使用

使用 EXPLAIN 可查看只读分析引擎中,执行查询语句时选用的执行计划,这是经过内部优化器进行多个阶段优化后,最终选出来的最优查询计划。查看执行计划时不会真正的执行 SQL,仅会输出执行计划。
EXPLAIN 示例如下:
EXPLAIN <SELECT_STATMENT>

explain select * from t1 left join t2 on t1.id = t2.id;
返回结果如下:
+---------------------------------------------------------------------------------+
| query plan |
+---------------------------------------------------------------------------------+
| ============================================ |
| |ID|OPERATOR |NAME|EST.ROWS| |
| -------------------------------------------- |
| |0 |HASH JOIN | |12500.00| |
| |1 |├─TABLE FULL SCAN (B) |t2 |10000.00| |
| |2 |└─TABLE FULL SCAN (P) |t1 |10000.00| |
| -------------------------------------------- |
| Details: |
| ------------------------------------- |
| 0 - JOIN TYPE: left outer join, EQUAL: [eq(singleton.t1.id, singleton.t2.id)] |
| 1 - STORAGE: LIBRASTORE, BLOCK OFFSET: 1 |
| 2 - STORAGE: LIBRASTORE, BLOCK OFFSET: 1 |
+---------------------------------------------------------------------------------+

EXPLAIN 结果解读

EXPLAIN 的返回结果包含以下字段:
ID 为算子在计划中展示的编号,从0开始往下逐级递增,方便用户用于查看 detail。
OPERATOR 为算子名称,代表着 SQL 执行过程中每一步进行的操作。
NAME 显示在查询中所访问到的表、分区等信息。
EST.ROWS 显示只读分析引擎根据统计信息估算出来的每个算子预计会处理的行数,如果没有统计信息,则会基于一个默认值进行计算显示。

算子介绍

算子是为了返回查询结果而执行的特定步骤,下表为只读分析引擎目前支持的各类算子名称及其作用介绍:
算子名称
算子介绍
SORT
SORT 算子用于对输入的数据进行排序。
TOPN
如果 ORDER BY 语句块后面还有 LIMIT 语句,优化器会进一步优化执行计划,生成 TOP-N SORT 算子,采用堆排序来选择 TOP-N 的数据。
LIMIT
LIMIT 算子用于限制数据输出的行数,这与 MySQL 的 LIMIT 算子功能相同。
FILTER
FILTER 算子用于对数据按指定谓词条件进行过滤操作,通常出现在 WHERE/HAVING/ON 子句中。
HASH JOIN
利用 HASH JOIN 来进行大数据集的 JOIN 操作。优化器使用两个数据集中表,较小的那个在内存中根据 JOIN 条件构建 HASH 表,之后数据库扫描更大的数据集,探测 HASH 表找到满足关联条件的行。
COLUMN READ
延迟物化算子,只读分析引擎支持下推部分过滤条件到 TableScan 算子,即先扫描过滤条件相关的列数据,过滤得到符合条件的行后,再扫描这些行的其他列数据,继续后续计算,从而减少 IO 扫描和数据处理的计算量。
TABLE FULL SCAN
对目标表进行全表扫描。
UINION
UNION 算子用于将两个查询的结果集进行并集运算。
WINDOW FUNCTION
WINDOW FUNCTION 算子用于实现 SQL 中的分析函数(也叫窗口函数),计算窗口内的相关行的结果,窗口函数每组可以返回多行,组内每一行都是基于窗口的逻辑计算的结果。
HASH GROUP BY
GROUP BY 算子主要用于在 SQL 中进行分组聚合计算操作,对于普通的聚合函数(SUM/MAX/MIN/AVG/COUNT/STDDEV)都是通过分配 GROUP BY 算子来完成。
PROJECTION
投影算子,对应 SQL 语句中的 SELECT 列表,功能是将每一条输入数据映射成新的输出数据。
EXCHANGE RECEIVER
数据接收算子,用于在执行 MPP 查询各个计算节点交换数据时,接收数据用。
EXCHAGE SENDER
数据发送算子,用于在执行 MPP 查询各个计算节点交换数据时,发送数据用。

Detail 信息

除了上述返回结果表格中展示的信息以外,可以看到在下方还会展示一个 Detail 项,Detail 项中展示了每个算子所带有的一些额外的信息,其格式呈 n - detail info,其中 n 代表的是每个算子的 ID,后面则是每个算子的具体信息。下表列出了每个算子会展示出的具体信息。
算子名称
Detail 信息
SORT
ORDER BY KEY:代表排序算子所采用的排序键。
TOPN
ORDER BY KEY:代表排序算子所采用的排序键。
OFFSET:Limit 操作所指定的偏移量。
COUNT:Limit 操作所指定的保留行数。
LIMIT
OFFSET:Limit 操作所指定的偏移量。
COUNT:Limit 操作所指定的保留行数。
FILTER
CONDITIONS:代表 FILTER 算子在过滤数据时所采用的谓词条件。
HASH JOIN
JOIN TYPE:当前 JOIN 的类型,如:inner join、left outer join、semi join 等。
NON EQUAL:当前 JOIN 是否是笛卡尔积,如果没有这个字段,则代表其不是笛卡尔积。
EQUAL:显示两个表进行 JOIN 时采用的等值条件。
OTHER COND:显示两个表进行 JOIN 时的非等值条件。
此外可以看到上文中 EXPLAIN 结果中 ID 为1和2的算子名称后面分别跟了(B)和(P)标志,这两个标志标记了在进行 HASH JOIN 操作时的 Build 与 Probe 端,B 代表 Build,P 代表 Probe。
COLUMN READ
COLUMN READ:延迟物化所读取的列名字。
TABLE FULL SCAN
STORAGE:所读取的底层存储类型,目前支持两种类型,为 LIBRASTORE、TDSQL。
BLOCK OFFSET:当前表在整条 SQL 所处的 Query Block 编号,用于辅助 Hint 使用。
UINION
无。
WINDOW FUNCTION
WINDOW FUCN DESCS:窗口函数名称。
PARTITION BY:分区键。
ORDER BY:排序所采用的排序键。
FRAME:窗口函数的窗口定义。
HASH GROUP BY
GROUP BY:执行聚合函数时指定的 group by key。
AGG FUNCS:SQL 中指定的聚合函数。
PROJECTION
EXPRS:PROJECTION 算子执行的表达式列表,主要是执行的 cast、还有各种 scalarfunc。
EXCHANGE RECEIVER
无。
EXCHAGE SENDER
ExchangeType:交换数据采用的方式:
PASS:将多个节点的数据发送往一个节点。
BCJ:将一个节点的数据广播到多个节点。例如 JOIN 时将 build 表的数据广播到各个节点,以便执行 JOIN 操作。
HASH:将数据通过 HASH 函数散列后分发到各个节点。例如用于 JOIN 时将左右两表数据打散重新分布。
HASH (BY PARTITION):当两表 JOIN,其中一个表的 join key 是 partition key 时,将另一个表按照 join key 是 partition key 的表分布方式 shuffle 出去。
除了上述表中算子的基本信息外,当开启了 runtime filter 算子且计划中有 HASH JOIN 时,HASH JOIN 算子两侧可能带有以下两种特殊的 detail 信息。
Probe Runtime Filters:当算子上有这个信息时,代表当前算子 apply 了 runtime filter 以过滤冗余数据。
Build Runtime Filters:此信息只会出现在 JOIN 算子上,代表当前 JOIN 算子的 build 侧生成了一个 runtime fileter,以提前过滤 probe 侧冗余数据,具体 runtime filter 的使用、调优以及显示信息的具体作用,可参考 Runtime Filter 使用手册
EXPLAIN 执行后,不同算子返回不同的信息。您可以使用 Optimizer Hints 来控制优化器的行为,以此控制物理算子的选择。
例如 /*+ HASH_JOIN_PROBE(t1) */ 表示优化器将强制采用 t1表作为 hash join 中的 probe 表。