创建索引前后执行计划的变更和软硬解析的比较

环境:OEL+Oracle 10.2.0.5 Rac

今天在itpub上回答一个网友的提问,RT:我第一次执行了一条sql之后,这条sql通过了硬解析,得到了执行计划,当再次执行这条sql时,会进行软解析是吧,不会通过优化器得到新的执行计划。如果我增加了一条索引,通过索引执行这条sql更好,在执行这条sql是进行软解析吗?(统计信息的改变,会导致sql进行硬解析吗?)

我当时的回答是:有索引了,统计信息变了。走索引了,执行计划变了。 但是软硬解析是对于SQL语句而言的吧?只要共享池中存在此SQL副本,将直接执行软解析;个人认为未经analyze表前,会被软解析

答案应该是硬解析;

中午午休的时候,趴那儿回顾了一下这个案例,但是思前想后总感觉有点不对,一切以事实说话,决定起来测试一下;测试过程和结果如下:

 

SQL> show user

USER is "SYS"

SQL> drop index tt_idx;

drop index tt_idx

           *

ERROR at line 1:

ORA-01418: specified index does not exist





SQL> drop table tt purge;

drop table tt purge

           *

ERROR at line 1:

ORA-00942: table or view does not exist


创建一张新表TT:

 

 

SQL> create table tt as select * from dba_objects;



Table created.


打开autotrace并开始第一次根据条件检索新表tt:

 

 

SQL> set autotrace on;  

SQL> select object_id,object_name from tt where object_id=10;  

  

 OBJECT_ID       OBJECT_NAME</span>  

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

        10       C_USER#  

  

Execution Plan  

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

Plan hash value: 264906180  

  

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

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

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

|   0 | SELECT STATEMENT  |      |     8 |   632 |   156   (1)| 00:00:02 |  

|*  1 |  TABLE ACCESS FULL| TT   |     8 |   632 |   156   (1)| 00:00:02 |  

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

  

Predicate Information (identified by operation id):  

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

  

   1 - filter("OBJECT_ID"=10)  

  

Note  

-----  

   - dynamic sampling used for this statement  

  

  

Statistics  

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

         68  recursive calls  

          0  db block gets  

        785  consistent gets  

        701  physical reads  

          0  redo size  

        481  bytes sent via SQL*Net to client  

        400  bytes received via SQL*Net from client  

          2  SQL*Net roundtrips to/from client  

          0  sorts (memory)  

          0  sorts (disk)  

          1  rows processed  

  

SQL>   


 


可以很清晰的从执行计划中看出,优化器走了全表扫描,并执行了硬解析;

 

再次执行上述查询:

 

SQL> select object_id,object_name from tt where object_id=10;  

  

 OBJECT_ID      OBJECT_NAME 

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

        10      C_USER#  

  

Execution Plan  

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

Plan hash value: 264906180  

  

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

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

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

|   0 | SELECT STATEMENT  |      |     8 |   632 |   156   (1)| 00:00:02 |  

|*  1 |  TABLE ACCESS FULL| TT   |     8 |   632 |   156   (1)| 00:00:02 |  

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

  

Predicate Information (identified by operation id):  

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

  

   1 - filter("OBJECT_ID"=10)  

  

Note  

-----  

   - dynamic sampling used for this statement  

  

  

Statistics  

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

          0  recursive calls  

          0  db block gets  

        707  consistent gets  

          0  physical reads  

          0  redo size  

        481  bytes sent via SQL*Net to client  

        400  bytes received via SQL*Net from client  

          2  SQL*Net roundtrips to/from client  

          0  sorts (memory)  

          0  sorts (disk)  

          1  rows processed  

  

SQL>   


 

执行计划虽依然走全表扫描,但是执行了软解析,这里的主要原因是在共享池中存在同样的SQL语句的一个副本(两条语句一模一样)

 

 

SQL> select object_id,OBJECT_NAME from tt where object_id=10;

  

 OBJECT_ID          OBJECT_NAME

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

        10          C_USER#  

  

Execution Plan  

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

Plan hash value: 264906180  

  

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

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

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

|   0 | SELECT STATEMENT  |      |     8 |   632 |   156   (1)| 00:00:02 |  

|*  1 |  TABLE ACCESS FULL| TT   |     8 |   632 |   156   (1)| 00:00:02 |  

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

  

Predicate Information (identified by operation id):  

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

  

   1 - filter("OBJECT_ID"=10)  

  

Note  

-----  

   - dynamic sampling used for this statement  

  

  

Statistics  

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

          4  recursive calls  

          0  db block gets  

        779  consistent gets  

          0  physical reads  

          0  redo size  

        481  bytes sent via SQL*Net to client  

        400  bytes received via SQL*Net from client  

          2  SQL*Net roundtrips to/from client  

          0  sorts (memory)  

          0  sorts (disk)  

          1  rows processed  

  

SQL> select OBJECT_ID,OBJECT_NAME from tt where object_id=10;  



 OBJECT_ID      OBJECT_NAME

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

        10      C_USER#  

  

Execution Plan  

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

Plan hash value: 264906180  

  

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

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

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

|   0 | SELECT STATEMENT  |      |     8 |   632 |   156   (1)| 00:00:02 |  

|*  1 |  TABLE ACCESS FULL| TT   |     8 |   632 |   156   (1)| 00:00:02 |  

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

  

Predicate Information (identified by operation id):  

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

  

   1 - filter("OBJECT_ID"=10)  

  

Note  

-----  

   - dynamic sampling used for this statement  

  

  

Statistics  

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

          4  recursive calls  

          0  db block gets  

        779  consistent gets  

          0  physical reads  

          0  redo size  

        481  bytes sent via SQL*Net to client  

        400  bytes received via SQL*Net from client  

          2  SQL*Net roundtrips to/from client  

          0  sorts (memory)  

          0  sorts (disk)  

          1  rows processed  

  

SQL>   


 


如上,SQL语句不同,便会执行硬解析。

 

ps:由于没有对表TT做分析,所以以上执行计划中的ROWS值为8而不是1(只要一条返回记录);

继续测试:

在表TT的object_id列添加索引TT_IDX,并执行上面一样的SQL语句进行检索:

 

SQL> create index tt_idx on tt(object_id);



Index created.



SQL> 
SQL> select object_id,object_name from tt where object_id=10;



 OBJECT_ID           OBJECT_NAME

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

        10           C_USER#







Execution Plan

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

Plan hash value: 2072537773

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

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

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

|   0 | SELECT STATEMENT            |        |     1 |    79 |     2   (0)| 00:00:01 |

|   1 |  TABLE ACCESS BY INDEX ROWID| TT     |     1 |    79 |     2   (0)| 00:00:01 |

|*  2 |   INDEX RANGE SCAN          | TT_IDX |     1 |       |     1   (0)| 00:00:01 |

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





Predicate Information (identified by operation id):

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



   2 - access("OBJECT_ID"=10)



Note

-----

   - dynamic sampling used for this statement



Statistics

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

          9  recursive calls

          0  db block gets

         79  consistent gets

          1  physical reads

          0  redo size

        481  bytes sent via SQL*Net to client

        400  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          1  rows processed



SQL> 

实验证明,虽然该条语句跟在之前执行过,并且SQL共享区有该语句的副本,但是依然执行了硬解析,且优化器走了索引;
在10g及以上版本中,如果表没有经过分析,oracle 自动通过动态采样的方式来收集分析数据。

 



 

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

版权所有,转载请注明作者及原文链接,否则追究法律责任!

QQ:      584307876

作者:    Seven

原文链接:http://blog.csdn.net/sunjiapeng/article/details/10592205

邮箱:     [email protected]

你可能感兴趣的:(执行计划)