加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

浅谈ORACLE执行计划顺序

(2012-10-26 16:33:31)
标签:

杂谈

分类: 数据库

浅谈ORACLE执行计划顺序

最近在做一个并发4000个用户的项目,每个月的单表数据量在20多万,这样在开发报表的时候,如果不注意查询优化,查询时间一长或者语句的复杂度比较高的话,经常会查死为了看SQL是否达到查询的性能要求,所以必须学会通过看执行计划来分析SQL语句。当然,优化的途径有很多,从硬件到软件都有涉及,本文主要通过以下几个方面聊一下执行计划。文中内容大部分是上网看了N多大侠们的高论,找到自己需要的信息总结一下,以备查看。

1、执行计划中的几个关键词

Full Table Scans         全表扫描:表中所有数据依次全部扫描一遍
Table Access by ROWID    通过rowid扫描:通过rowid直接扫面对应数据
index unique scan        索引唯一扫描:通过唯一索引直接扫描对应数据
index range scan         索引范围扫描
index full scan          索引全扫描
Hash Join *              哈希链接:多表关联查询时使用
Sort *                   排序
Hash Group By            分组:对按照分组条件相同的数据合并成一条
View                     作为视图使用

Operation 操作项
Name 执行对象名称,索引还是数据实体表
Rows,Cost 这几项都是代表消耗的字段,值越低越好

2、查看执行计划的顺序

查看执行计划有两种方式,一种是摁F5出来的执行计划的窗口,这样执行出来的执行计划是个预估值;另外一种是执行下面两条语句来查看,这样出来的执行计划是实际执行的计划值。后者要比前者详细,一般建议通过后者来查看。

explain plan for
select * from table(dbms_xplan.display);、

下面通过一个实际的执行计划来分析一下。

先看SQL:

select vwocode, pk_corp
                  from pd_sdintimemonitor sa
                 where sa.querytime > ’2011-05-09 00:00:00′
                   and sa.querytime < ’2011-05-16 00:00:00′
                   and sa.islate = ‘N’
                   and sa.pk_filiale  =’1348′
                   and sa.pk_prod = ’2017′
                   and not exists
                 (select vwocode
                          from pd_sdintimemonitor s
                         where sa.vwocode = s.vwocode
                           and s.islate = ‘Y’
                           and s.pk_filiale = ’1348′
                           )

执行计划:  
——————————————————————————————————————– 
| Id  | Operation                         | Name                   | Rows  | Bytes |TempSpc| Cost (%CPU)| Time    
——————————————————————————————————————– 
  0 | SELECT STATEMENT                                           1 |    17 |       | 79077   (1)| 00:15:49 | 
  1 |  SORT AGGREGATE                                            1 |    17 |                        
  2 |   VIEW                                                  | 11206 |   186K|       | 79077   (1)| 00:15:49 | 
  3 |    HASH GROUP BY                                        | 11206 |   361K|       | 79077   (1)| 00:15:49 | 
  4 |     VIEW                                                | 11206 |   361K|       | 79077   (1)| 00:15:49 | 
  5 |      HASH GROUP BY                                      | 11206 |  1170K|  2648K| 79077   (1)| 00:15:49 | 
|*  6 |       HASH JOIN RIGHT ANTI                              | 11206 |  1170K|  3064K| 78803   (1)| 00:15:46 | 
|*  7 |        TABLE ACCESS BY INDEX ROWID| PD_SDINTIMEMONITOR      100K|  1873K|       | 78085   (1)| 00:15:38 | 
|*  8 |         INDEX RANGE SCAN          | I_PD_SDINTIMEMONITOR_1 |   213K|             431   (1)| 00:00:06 | 
|*  9 |        TABLE ACCESS BY INDEX ROWID| PD_SDINTIMEMONITOR      112K|  9642K|         34   (0)| 00:00:01 | 
|* 10 |         INDEX RANGE SCAN          | I_PD_SDINTIMEMONITOR_2 |    88 |                (0)| 00:00:01 | 
——————————————————————————————————————– 
  
Predicate Information (identified by operation id): 
————————————————— 
  6 – access(“SA”.”VWOCODE”=”S”.”VWOCODE”) 
   7 – filter(“S”.”ISLATE”=’Y') 
   8 – access(“S”.”PK_FILIALE”=’1348′) 
   9 – filter(“SA”.”PK_PROD”<>2017 AND “SA”.”PK_FILIALE”=’1348′ AND “SA”.”ISLATE”=’N') 
  10 – access(“SA”.”QUERYTIME”>’2011-05-09 00:00:00′ AND “SA”.”QUERYTIME”<’2011-05-16 00:00:00′) 

上面的执行计划有两部分,上部分是执行计划整体的步骤和消耗查看,下面的部分是针对ID记录的各个步骤的SQL语句执行情况描述。
可以看到Operation这一列的步骤是个树,SELECT STATEMENT为树根节点,SORT AGGREGATE为它的子节点,一个跟节点可以有多个子节点,展开是由上到下,从左到右,表示oracle读取SQL的过程,而真正SQL执行的先后顺序是从父节点开始找,有子节点先执行子节点,有多个子节点先执行从上向下的第一个,子节点全部执行完毕再执行父节点

按照从根节点到子节点,子节点间从上到下执行,上面的步骤应该是8-7-10-9-6-543210。而参照执行计划的下半部分和SQL,可以看出,查询在执行的时候是按照下面的实际步骤进行的:

(1)步骤8,使用索引(I_PD_SDINTIMEMONITOR_1 ),通过索引范围扫描(INDEX RANGE SCAN),得出索引对应的rowid集合R1。即通过语句
and s.pk_filiale = ’1348′ 从 pd_sdintimemonitor s 中使用索引找到R1;对应子查询中的SQL:
 select vwocode from pd_sdintimemonitor s where  s.pk_filiale = ’1348′

(2)步骤7,根据(1)中得到的R1,加上过滤条件 and s.islate = ‘Y’ 到用相应的ROWID到数据库中找到相应的数据行,这样就得到了数据集D1;

(3)步骤10,使用索引(I_PD_SDINTIMEMONITOR_2 ),同样通过索引范围扫描(INDEX RANGE SCAN),得出索引对应的rowid集合R2。语句为主查询中的
select vwocode, pk_corp from pd_sdintimemonitor sa
where sa.querytime > ’2011-05-09 00:00:00′ and sa.querytime < ’2011-05-16 00:00:00′ 得到R2;

(4)步骤9,用(3)中得到的R2,加上过滤条件
and sa.islate = ‘N’ and sa.pk_filiale  =’1348′ and sa.pk_prod = ’2017′ 查询得到结果集D2;

(5)步骤6,把D1和D2用vwocode链接成一个数据集D3,语句为 sa.vwocode = s.vwocode

(6)步骤5,对(5)中得到的数据集D3分组合并成一个临时视图view1;

(7)同理,步骤3和步骤2,对view1再次进行分组合并成最后的结果。
—————————————————————————————————————-
ps:对于如何通过索引查找数据,如何确定是否走索引等后续文章再写,暂时本文只讨论下执行计划如何走的。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有