您的位置:首页 > 其它

当统计信息不准确时,CBO可能产生错误的执行计划,并在10053 trace中找到CBO出错的位置示例

2013-02-18 21:28 603 查看
一、本文说明:

操作系统:rhel 5.4 x32

数据库:oracle 11g r2 x32

二、实验内容:

----创建一张jack表,并创建索引jack_ind----
1 SQL> create table jack as select * from dba_objects;

Table created.

SQL> create index jack_ind on jack(object_id);

Index created.

----先做一下统计信息,并连带索引----
9 SQL> exec dbms_stats.gather_table_stats(user,'jack',cascade=>true);

PL/SQL procedure successfully completed.

SQL> set autotrace traceonly;
SQL> set linesize 120;
----当object_id=100时的值是唯一的,所以查询会走索引----
15 SQL> select * from jack where object_id=100;

Execution Plan
----------------------------------------------------------
Plan hash value: 2860868395

----------------------------------------------------------------------------------------
| Id  | Operation            | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |           |     1 |    97 |     2     (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| JACK     |     1 |    97 |     2     (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN        | JACK_IND |     1 |       |     1     (0)| 00:00:01 |
----------------------------------------------------------------------------------------

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

2 - access("OBJECT_ID"=100)

Statistics
----------------------------------------------------------
1  recursive calls
0  db block gets
4  consistent gets

SQL> set autotrace off;
----再把所有object_id的值修改成100---
43 SQL> update jack set object_id=100;

72489 rows updated.

SQL> set autotrace traceonly;
SQL> alter session set events '10053 trace name context forever,level 1';

Session altered.

----因为现在object_id的值全部都是100了,所以不应该走索引而走全表----
52 SQL> select * from jack where object_id=100;

72489 rows selected.

Execution Plan
----------------------------------------------------------
Plan hash value: 2860868395

----------------------------------------------------------------------------------------
| Id  | Operation            | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |           |     1 |    97 |     2     (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| JACK     |     1 |    97 |     2     (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN        | JACK_IND |     1 |       |     1     (0)| 00:00:01 |
----------------------------------------------------------------------------------------
68                                                               -----------在这里可以看到执行计划依然走的是索引,而Rows=1,显然执行计划是错误的。
Predicate Information (identified by operation id):
---------------------------------------------------

2 - access("OBJECT_ID"=100)

Statistics
----------------------------------------------------------
0  recursive calls
0  db block gets
10860  consistent gets
0  physical reads
SQL> alter session set events '10053 trace name context off';

Session altered.

SQL> set autotrace off;
SQL> @/u01/scripts/showtrace

trace_file_name
------------------------------------------------------------------------------------------------------------------------
/u01/app/oracle/diag/rdbms/yft/yft/trace/yft_ora_4005.trc

----退出再进,并对表jack进行一下统计信息----
93 SQL> exec dbms_stats.gather_table_stats(user,'jack',cascade=>true);

PL/SQL procedure successfully completed.

SQL> set autotrace trace exp;
SQL> alter session set events '10053 trace name context forever,level 1';

Session altered.

----查询object_id=100时,执行计划走了全表,显然这次是正确的----
102 SQL> select * from jack where object_id=100;

Execution Plan
----------------------------------------------------------
Plan hash value: 949574992

--------------------------------------------------------------------------
| Id  | Operation      | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |     | 72482 |  6724K|   290   (1)| 00:00:04 |
|*  1 |  TABLE ACCESS FULL| JACK | 72482 |  6724K|   290   (1)| 00:00:04 |
--------------------------------------------------------------------------
114                                                         -----在这里Rows=72482已经很接近72489了
Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter("OBJECT_ID"=100)

SQL> alter session set events '10053 trace name context off';

Session altered.

SQL> set autotrace off;
SQL> @/u01/scripts/showtrace

trace_file_name
--------------------------------------------------------------------------------
/u01/app/oracle/diag/rdbms/yft/yft/trace/yft_ora_4032.trc

----先看一下yft_ora_4005.trc中的内容,这个是错误的执行计划的内容-----
131 ***************************************
BASE STATISTICAL INFORMATION
***********************
Table Stats::
Table: JACK  Alias: JACK
#Rows: 72489  #Blks:  1058  AvgRowLen:  97.00
Index Stats::
Index: JACK_IND  Col#: 4
LVLS: 1  #LB: 161  #DK: 72489  LB/K: 1.00  DB/K: 1.00  CLUF: 1656.00
Access path analysis for JACK                                              ----在10053事件trace文件中我们可以发现#DK的值依然是72489,说明不同值有72489个,才导致执行计划错误。
***************************************
SINGLE TABLE ACCESS PATH
Single Table Cardinality Estimation for JACK[JACK]
Table: JACK  Alias: JACK
Card: Original: 72489.000000  Rounded: 1  Computed: 1.00  Non Adjusted: 1.00
Access Path: TableScan
Cost:  289.48  Resp: 289.48  Degree: 0
Cost_io: 288.00  Cost_cpu: 26381844
Resp_io: 288.00  Resp_cpu: 26381844
Access Path: index (AllEqRange)
Index: JACK_IND
resc_io: 2.00  resc_cpu: 15723
ix_sel: 0.000014  ix_sel_with_filters: 0.000014
Cost: 2.00  Resp: 2.00  Degree: 1
Best:: AccessPath: IndexRange
Index: JACK_IND
Cost: 2.00  Degree: 1  Resp: 2.00  Card: 1.00  Bytes: 0

***************************************

----先看一下yft_ora_4032.trc中的内容,这个是错误的执行计划的内容-----
161
***************************************
BASE STATISTICAL INFORMATION
***********************
Table Stats::
Table: JACK  Alias: JACK
#Rows: 72489  #Blks:  1058  AvgRowLen:  95.00
Index Stats::
Index: JACK_IND  Col#: 4
LVLS: 1  #LB: 250  #DK: 1  LB/K: 250.00  DB/K: 1032.00  CLUF: 1032.00
Access path analysis for JACK                                              ----当进行统计信息以后#DK的值已经变成1了,而表中object_id的值就只有1个了--100。所以CBO选择了全表
***************************************
SINGLE TABLE ACCESS PATH
Single Table Cardinality Estimation for JACK[JACK]
Table: JACK  Alias: JACK
Card: Original: 72489.000000  Rounded: 72482  Computed: 72482.35  Non Adjusted: 72482.35
Access Path: TableScan
Cost:  290.38  Resp: 290.38  Degree: 0
Cost_io: 288.00  Cost_cpu: 42327664
Resp_io: 288.00  Resp_cpu: 42327664
Access Path: index (AllEqRange)
Index: JACK_IND
resc_io: 1282.00  resc_cpu: 54794826
ix_sel: 0.999908  ix_sel_with_filters: 0.999908
Cost: 1285.08  Resp: 1285.08  Degree: 1
Best:: AccessPath: TableScan
Cost: 290.38  Degree: 1  Resp: 290.38  Card: 72482.35  Bytes: 0

***************************************
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: