在PolarDB-X中,一条SQL语句会被拆分并下发到多个存储节点(DN)并行执行。由于各节点数据分布或统计信息可能存在差异,会导致其执行计划不一致,进而引发性能问题。通过EXPLAIN系列语法,您可以查看SQL在每个DN上的实际执行计划,从而快速定位并诊断因执行计划不一致或估算不准引起的性能瓶颈。
功能简介
PolarDB-X包含计算节点(CN)和存储节点(DN)。客户端的SQL请求首先到达计算节点(CN),CN负责SQL解析、优化并生成逻辑执行计划,然后将物理SQL下发到存储节点(DN)执行。DN执行计划即物理SQL在DN上的执行计划。
由于DN执行计划直接影响查询性能,PolarDB-X提供了多种EXPLAIN ... EXECUTE
命令来满足不同的诊断需求。您可以根据下表选择合适的命令:
命令 | 适用场景 |
| 快速诊断。默认聚合所有DN的执行计划信息,通过 |
| 定位差异。当 |
| 全面分析。显示所有DN上的执行计划详情,适用于需要完整、逐一排查的场景。注意,输出内容可能较多。 |
| 高级分析。与MySQL 8.0兼容,以树状、JSON或运行时统计(ANALYZE)的格式展示单个DN的执行计划,用于进行更深入的成本和性能分析。 |
前提条件
仅支持实例版本为polardb-2.5.0_5.4.20-20250618_xcluster8.4.20-20250612
及以上版本。
快速诊断:EXPLAIN EXECUTE
当实例版本为polardb-2.5.0_5.4.20-20250618_xcluster8.4.20-20250612
及以上版本时,EXPLAIN EXECUTE
默认会将所有物理SQL下发至相应的DN节点上的物理表,并收集与对比所有物理SQL的DN执行计划。在该版本之前,EXPLAIN EXECUTE
仅随机选择一条物理SQL来展示其DN执行计划。
EXPLAIN EXECUTE
是诊断的起点。它默认会收集并对比所有DN的执行计划,其结果与MySQL原生EXPLAIN
格式基本一致,但在Extra
列增加了两个关键信息,帮助您快速发现问题:
Different plan(phyTb_1, phyTb_2, ...)
:表示列出的物理分表与其他分表所选择的DN执行计划不同(例如索引选择不同)。Scan rows(min, max)
:表示所有物理分表在DN优化器估算的扫描行数范围。如果min和max值差异巨大,可能存在数据倾斜。
示例:
mysql> EXPLAIN EXECUTE SELECT col1 FROM exe_tb WHERE col1 < 6\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: exe_tb
partitions: NULL
type: index
possible_keys: auto_shard_key_col1
key: auto_shard_key_col1
key_len: 5
ref: NULL
rows: 2000
filtered: 100
Extra: Different plan(exe_tb_58Db_00001,exe_tb_58Db_00015); Scan rows(1, 66819); Using where; Using index
从Extra
列可知:物理表exe_tb_58Db_00015
的执行计划与exe_tb_58Db_00001
(以及其他未列出的分表)不同。同时,各分表扫描行数从1到66819不等,差异悬殊,可能存在数据倾斜。
详细分析:查看差异与全部计划
当发现计划不一致时,您可以使用EXPLAIN DIFF_EXECUTE
来查看具体差异,或使用EXPLAIN ALL_EXECUTE
查看全部分片的计划详情。
定位差异:EXPLAIN DIFF_EXECUTE
该命令会直接列出存在差异的物理表的DN执行计划,其中table
列直接显示物理表名。
对于物理表
exe_tb_xxDb_00001
,访问类型(type
)为index
,表示使用了索引,效率较高。对于物理表
exe_tb_xxDb_00015
,访问类型为ALL
,表示进行了全表扫描,效率较低。
通过对比,您可以清晰地定位到是哪个物理分片上的查询计划出现了问题。
mysql> EXPLAIN DIFF_EXECUTE SELECT col1 FROM exe_tb WHERE col1 < 6\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: exe_tb_58Db_00001
type: index
possible_keys: auto_shard_key_col1
key: auto_shard_key_col1
key_len: 5
ref: NULL
rows: 2000
filtered: 100
Extra: Different plan(exe_tb_58Db_00001,exe_tb_58Db_00015); Scan rows(1, 44939); Using where; Using index
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: exe_tb_58Db_00015
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 1009
filtered: 33.32999801635742
Extra: Using where
全面分析:EXPLAIN ALL_EXECUTE
该命令会直接列出所有物理表的DN执行计划,其中table
列直接显示物理表名。
mysql> EXPLAIN ALL_EXECUTE SELECT col1 FROM exe_tb WHERE col1 < 6\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: exe_tb_58Db_00001
partitions: NULL
type: index
possible_keys: auto_shard_key_col1
key: auto_shard_key_col1
key_len: 5
ref: NULL
rows: 2000
filtered: 100
Extra: Different plan(exe_tb_58Db_00001,exe_tb_58Db_00015); Scan rows(1, 44939); Using where; Using index
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: exe_tb_58Db_00004
partitions: NULL
type: range
possible_keys: auto_shard_key_col1
key: auto_shard_key_col1
key_len: 5
ref: NULL
rows: 44939
filtered: 100
Extra: Using where; Using index
*************************** 3. row ***************************
id: 1
select_type: SIMPLE
table: exe_tb_58Db_00005
partitions: NULL
type: index
possible_keys: auto_shard_key_col1
key: auto_shard_key_col1
key_len: 5
ref: NULL
rows: 1
filtered: 100
Extra: Using where; Using index
************** 此处省略其他物理表的执行计划... ********************
高级分析
为便于进行更精细的性能分析,PolarDB-X支持多种与MySQL 8.0兼容的输出格式(TREE
、JSON
或ANALYZE
)。
EXPLAIN TREE_EXECUTE
:以更易读的树状结构展示执行计划。EXPLAIN JSON_EXECUTE
:以JSON格式输出DN优化器的详细信息。EXPLAIN ANALYZE_EXECUTE
:实际执行SQL,并展示执行过程的统计信息和代价。
默认情况下,EXPLAIN TREE_EXECUTE
、EXPLAIN JSON_EXECUTE
和EXPLAIN ANALYZE_EXECUTE
只会随机选择一个DN并展示其执行计划。如需查看所有DN的详细计划,请在SQL语句前添加Hint /*+TDDL:EXPLAIN_EXECUTE_PHYTB_LEVEL=2*/
。
EXPLAIN TREE_EXECUTE
mysql> EXPLAIN TREE_EXECUTE SELECT col1 FROM exe_tb WHERE col1 < 6;
+------------------------+------------------------------------------------------------+
| TABLE | PHYSICAL_PLAN |
+------------------------+------------------------------------------------------------+
| [[exe_tb_58Db_00001]]
| -> Filter: (exe_tb.col1 < 6) (cost=202.75 rows=2000)
-> Index scan on exe_tb using auto_shard_key_col1 (cost=202.75 rows=2000)
|
+------------------------+------------------------------------------------------------+
PHYSICAL_PLAN
列以层级缩进的形式展示了执行计划树,执行流程从内层(缩进最深)向外层进行。在本例中,执行顺序为:
-> Index scan on exe_tb using col1
: 通过col1
索引扫描数据。-> Filter: (exe_tb.col1 < 6)
: 将索引扫描的结果进行过滤。
每一层都包含了优化器估算的成本(cost)和行数(rows),便于直观理解数据处理流程和各环节的开销。
EXPLAIN JSON_EXECUTE
mysql> EXPLAIN JSON_EXECUTE SELECT col1 FROM exe_tb WHERE col1 < 6;
+------------------------+------------------------------------------+
| TABLE | PHYSICAL_PLAN |
+------------------------+------------------------------------------+
| [[exe_tb_58Db_00001]]
| {
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "202.75"
},
"table": {
"table_name": "exe_tb",
"access_type": "index",
"possible_keys": [
"auto_shard_key_col1"
],
"key": "auto_shard_key_col1",
"used_key_parts": [
"col1"
],
"key_length": "5",
"rows_examined_per_scan": 2000,
"rows_produced_per_join": 2000,
"filtered": "100.00",
"using_index": true,
"cost_info": {
"read_cost": "2.75",
"eval_cost": "200.00",
"prefix_cost": "202.75",
"data_read_per_join": "31K"
},
"used_columns": [
"col1"
],
"attached_condition": "(`db0_p00000`.`exe_tb`.`col1` < 6)"
}
}
} |
+------------------------+------------------------------------------+
PHYSICAL_PLAN
列提供了一个详细的JSON对象,这对于深入分析优化器行为非常有用。关键字段包括:
cost_info
: 包含详细的查询成本(query_cost
)、读成本(read_cost
)、评估成本(eval_cost
)等。access_type
: 表的访问方式,此处为index
。key
: 实际选择的索引。rows_examined_per_scan
: 预估扫描的行数。
该格式提供了最全面的优化器估算信息,适合进行底层分析。
EXPLAIN ANALYZE_EXECUTE
EXPLAIN ANALYZE_EXECUTE
命令会实际执行SQL语句,在生产环境中对大数据量的表执行时,可能会消耗较多资源并产生慢查询,请谨慎使用。
mysql> EXPLAIN ANALYZE_EXECUTE SELECT col1 FROM exe_tb WHERE col1 < 6;
+------------------------+-----------------------------------------------------------------------------------------------------------+
| TABLE | PHYSICAL_PLAN |
+------------------------+-----------------------------------------------------------------------------------------------------------+
| [[exe_tb_58Db_00001]]
| -> Filter: (exe_tb.col1 < 6) (cost=202.75 rows=2000) (actual time=0.028..0.655 rows=2000 loops=1)
-> Covering index scan on exe_tb using auto_shard_key_col1 (cost=202.75 rows=2000) (actual time=0.026..0.468 rows=2000 loops=1)
|
+------------------------+-----------------------------------------------------------------------------------------------------------+
PHYSICAL_PLAN
列展示了DN上的执行计划树。其中actual time
显示了该算子实际执行的耗时(启动耗时..总耗时),rows
显示了实际返回的行数。这些信息对于分析具体算子的性能瓶颈至关重要。