Oracle SQL性能分析之10053事件

优化器生成正确执行计划的前提条件是要有正确的统计信息,不准确的统计信息往往会导致错误的执行计划。当通过SQL和基数推断出的执行计划和实际执行计划不同时,就可以借助10053事件。10053事件是用来诊断优化器如何估算成本和选择执行计划的,用它产生的trace文件提供了Oracle如何选择执行计划,为什么会得到这样的执行计划信息。和10046事件类似,它主要用于特殊情况下的分析和诊断。

1、测试环境:
SQL> select * from v$version;
BANNER
----------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production

2、建立测试对象
SQL> create table tabtemp as select * from dba_objects where object_id is not null;
Table created.

SQL> select count(object_id) from tabtemp;
COUNT(OBJECT_ID)
----------------
          72764

测试表object_id列的数值分布:
SQL> select count(distinct object_id) from tabtemp;
COUNT(DISTINCTOBJECT_ID)
------------------------
                  72764
建立索引:
SQL> create index idx_tabtemp_id on tabtemp(object_id);

3、生成10053事件
统计表及索引信息:
SQL> exec dbms_stats.gather_table_stats(user,'TABTEMP',cascade=>true);

查看执行计划:
SQL> alter session set tracefile_identifier='plan';
SQL> set autotrace trace exp;
SQL> alter session set events '10053 trace name context forever,level 1';

SQL> select * from tabtemp where object_id=3;
Execution Plan
----------------------------------------------------------
Plan hash value: 2221486709
--------------------------------------------------------------------------------------------
| Id  | Operation                  | Name          | Rows  | Bytes | Cost (%CPU)| Time    |
--------------------------------------------------------------------------------------------
|  0 | SELECT STATEMENT            |                |    1 |    97 |    2  (0)| 00:00:01 |
|  1 |  TABLE ACCESS BY INDEX ROWID| TABTEMP        |    1 |    97 |    2  (0)| 00:00:01 |
|*  2 |  INDEX RANGE SCAN          | IDX_TABTEMP_ID |    1 |      |    1  (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
  2 - access("OBJECT_ID"=3)
由执行计划可知,查询走索引,这是非常高效的查询方式。


更新测试表,将object_id列数值全部设置为3:
SQL> update tabtemp set object_id=3 where object_id!=3;
72763 rows updated.

SQL> commit;
SQL> select count(distinct object_id) from tabtemp;
COUNT(DISTINCTOBJECT_ID)
------------------------
                      1

不收集统计数据,查看执行计划:
SQL> set autotrace trace exp;
SQL> select * from tabtemp where object_id=3;
Execution Plan
----------------------------------------------------------
Plan hash value: 2221486709
-------------------------------------------------------------------------------------------
| Id  | Operation                  | Name          | Rows  | Bytes | Cost (%CPU)| Time    |
-------------------------------------------------------------------------------------------
|  0 | SELECT STATEMENT            |                |    1 |    97 |    2  (0)| 00:00:01 |
|  1 |  TABLE ACCESS BY INDEX ROWID| TABTEMP        |    1 |    97 |    2  (0)| 00:00:01 |
|*  2 |  INDEX RANGE SCAN          | IDX_TABTEMP_ID |    1 |      |    1  (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
  2 - access("OBJECT_ID"=3)
由输出结果可知,本次查询沿用原来的执行计划,是错误的执行计划。

重新对更新后的测试对象进行数据分析:
SQL> set autotrace off;
SQL> exec dbms_stats.gather_table_stats(user,'TABTEMP',cascade=>true);

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/e2463b9049f56d35e66b5f1b853c26d8.html