#执行计划
执行计划是SQL优化过程的重要辅助工具,通过执行计划可以确定优化器是否选出了最优的计划,或判断新增的索引是否生效。
一个执行计划定义了SQL引擎运行一条SQL语句的顺序和算法。可通过EXPLAIN命令或AUTOTRACE命令,在yasql客户端中查询执行计划。
典型的执行计划如下所示:
EXPLAIN SELECT branch_no FROM area a, branches b WHERE a.area_no = b.area_no;
PLAN_DESCRIPTION
----------------------------------------------------------------
SQL hash value: 3244719443
Optimizer: ADOPT_C
+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+
| Id | Operation type | Name | Owner | Rows | Cost(%CPU) | Partition info |
+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+
| 0 | SELECT STATEMENT | | | | | |
| 1 | NESTED LOOPS INNER | | | 100000| 690( 0)| |
| 2 | TABLE ACCESS FULL | BRANCHES | SYS | 100000| 442( 0)| |
| 3 | TABLE ACCESS BY INDEX ROWID | AREA | SYS | | | |
|* 4 | INDEX UNIQUE SCAN | SYS_C_18 | SYS | 1| 149( 0)| |
+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+
Operation Information (identified by operation id):
---------------------------------------------------
4 - Predicate : access("A"."AREA_NO" = "B"."AREA_NO")
执行计划实际上是一个二叉树结构,执行器以后序遍历的顺序执行计划中定义的算子。上述输出内容则是二叉树后序遍历转换成一维后所显示的样式。例如,本例中算子执行顺序为2->4->3->1->0。
ID
执行步骤的唯一标识,并不是执行顺序。
Operation type
执行算子,前面的空格标示计划的层次关系。没有下层计划的算子,例如2、4,表示将从数据库中检索数据,这些算子就是访问路径或用于检索数据的技术。
ID为2的算子表示使用全表扫描,从BRACHES表里检索所有行。
ID为4的算子表示在AREA表的索引中检索与BRANCHES.AREA_NO相等的ROWID,例如,AREA_ID为'01'的ROWID值是'AADShUAABAAAnPJAAK'。
ID为3的算子表示根据第四层检索出来的ROWID,访问AREA表获取该ROWID对应的数据行。
ID为1的算子表示对从BRANCHES和AREA表中取出来的数据做连接处理,并将处理结果返回给ID为0的算子,其中连接算法使用的是NESTED LOOP JOIN。
单机部署并行场景下或分布式部署中会使用PX(parallel excute)算子,实现跨节点间的数据发送和接收,例如本条语句在分布式部署中的执行算子信息如下:
+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+
| Id | Operation type | Name | Owner | Rows | Cost(%CPU) | Partition info |
+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+
| 0 | SELECT STATEMENT | | | | | |
| 1 | DISTRIBUTED COORDINATOR | | | | | |
| 2 | COL TO ROW | | | | | |
| 3 | PX N2I REMOTE | QUEUE_0 | | 100000| 1943( 0)| |
|* 4 | HASH JOIN INNER | | | 100000| 1604( 0)| |
|* 5 | PX N2N REMOTE | QUEUE_1 | | 100000| 606( 0)| |
| 6 | TABLE ACCESS FULL | AREA | SALES | 100000| 442( 0)| |
|* 7 | PX N2N REMOTE | QUEUE_2 | | 100000| 606( 0)| |
| 8 | TABLE ACCESS FULL | BRANCHES | SALES | 100000| 442( 0)| |
+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+
其中,'PX N2I REMOTE'表示多个DN上的数据向CN聚集,'PX N2N REMOTE'表示将DN上的数据进行哈希重分布。
Rows
优化器根据统计信息和特定算法计算出来的行数预估值,通常并不能精准体现最终执行计算出来的行数信息。
Cost
优化器根据算子和硬件等信息,算出的一个参考值,Cost值越大,表示该层计划占用的资源越大。
Partition info
算子扫描到的分区范围。