通过执行计划看sql的执行路径

今天又有网友问到了有关执行计划的步骤的问题。通过这个网友给的例子,我就简单的先讲讲执行计划里我们使用频率最高,也是最基础的一项,执行计划的路径问题。

 

这个网友给的是一个最简单的例子,是sample数据里的emp和dept的联合查询的例子

 

SQL>select ename,dname from emp,dept where emp.deptno=dept.deptno;

 

执行计划 
---------------------------------------------------------- 
Plan hash value: 351108634 

---------------------------------------------------------------------------------------- 
| Id  | Operation                    | Name    | Rows  | Bytes | Cost (%CPU)| Time    | 
---------------------------------------------------------------------------------------- 
|  0 | SELECT STATEMENT            |        |    14 |  308 |    4  (0)| 00:00:01 | 
|  1 |   NESTED LOOPS                |        |    14 |  308 |    4  (0)| 00:00:01 | 
|  2 |     TABLE ACCESS FULL          | EMP    |    14 |  126 |    3  (0)| 00:00:01 | 
|  3 |     TABLE ACCESS BY INDEX ROWID| DEPT    |    1 |    13 |    1  (0)| 00:00:01 | 
|*  4 |      INDEX UNIQUE SCAN        | PK_DEPT |    1 |      |    0  (0)| 00:00:01 | 
---------------------------------------------------------------------------------------- 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

  4 - access("EMP"."DEPTNO"="DEPT"."DEPTNO") 

 

以上是这个sql的执行计划,关于上面这个执行计划是如何出现的,这里不再赘述。我们直接从如何理解这个sql的执行路径开始。

 

通过这个sql和他的执行计划来看。这条SQL使用CBO的可能性高于RBO的可能性。虽然这里没有一个明确的Optimizer=XXXX的提示。主要是根据驱动表的顺序来猜测的,当然关于这个Optimizer并不是这里的主要内容。

 

那么根据这个执行计划的结果,我们如何来理解这个SQL的执行顺序叻,其实方法很简单,就是 同级,从上至下,不同级 从右及左。简单的口诀如此,

 

我们一起通过上面的实例来详细解释一下。

首先执行计划结果是一个树状结构,其中的一些step存在着父子的关系。最上面的就是root,我们可以把这个树简单的描述成

root

    first sub-statement

    second sub-statement

 

这里我们所说的同级,从上至下,不同级 从右及左, 表现就是,不同级 从右及左,也就是先执行子句(子句一般较右),子句的结果作为执行父句的依据。 所以这里要先执行完子句才用子句的返回来执行父句。 同级,从上至下, 就很好理解了,意味着first sub-statement和second sub-statement同级,那么先开始上面的,再执行底下的。

 

现在我们回看到这个sql的执行实例。

  0 | SELECT STATEMENT            |        |    14 |  308 |    4  (0)| 00:00:01 | 

这个是root,执行从这里开始。不过他下面还有

|  1 |   NESTED LOOPS                |        |    14 |  308 |    4  (0)| 00:00:01 | 

 

所以这里必须先执行完1,才能执行0的。 执行1,我们又可以看到。需要执行

|  2 |     TABLE ACCESS FULL          | EMP    |    14 |  126 |    3  (0)| 00:00:01 | 
|  3 |     TABLE ACCESS BY INDEX ROWID| DEPT    |    1 |    13 |    1  (0)| 00:00:01 | 

由于2下面已经没有子句了,所以这里2可以执行了,2执行完,接着还有3要执行呀。执行到3,我们又发现,3是需要先执行子句 

|*  4 |      INDEX UNIQUE SCAN        | PK_DEPT |    1 |      |    0  (0)| 00:00:01 | 

这样先执行了4, 执行完4,4的结果返回给3,作为3执行的一些输入。

 

当3执行完,汇总2,3的执行结果返回执行1. 1执行完,就返回作为0最后的结果,从而sql执行完毕

 

所以我们这里最后可以看到这个sql的执行路径是 (2)->(4)->(3)->(1)->(0)

 

既是emp full scan(2) ----> dept index scan(4) ----> 由索引得到rowid ,读取数据 (3) ----> (1)返回本次查询结果。嵌套循环,直到得到所有结果。

 

执行计划的结果和优化器的模式,数据库的统计信息都有着比较密切的联系。所以相同的sql在不同的数据库上,甚至有时候是相同的数据,都有可能是不一样的执行计划的。

 

比如,我机器上的这个sql的执行计划是

---------------------------------------------------------------------------

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

---------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |     4 |    40 |     7  (15)| 00:00:01 |

|*  1 |  HASH JOIN         |      |     4 |    40 |     7  (15)| 00:00:01 |

|   2 |   TABLE ACCESS FULL| EMP  |     4 |    12 |     3   (0)| 00:00:01 |

|   3 |   TABLE ACCESS FULL| DEPT |     5 |    35 |     3   (0)| 00:00:01 |

---------------------------------------------------------------------------

这里可以看到和网友的执行计划,相差很大,其实这里是基于CBO的,在不同的统计量下这个计划都会发生变化的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

inthirties

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值