当统计信息不准确时,CBO可能产生错误的执行计划,并在10053 trace中找到CBO出错的位置示例
2013-02-18 21:28
603 查看
一、本文说明:
操作系统:rhel 5.4 x32
数据库:oracle 11g r2 x32
二、实验内容:
操作系统: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 ***************************************
相关文章推荐
- Oracle CBO 统计信息的收集与执行计划的选择
- Oracle CBO 统计信息的收集与执行计划的选择
- 统计信息失准导致CBO选错执行计划一例
- SQL Server 更新统计信息出现严重错误,应放弃任何可能产生的结果
- 统计信息不准导致执行计划出错跑不出结果,优化后只要1分钟
- 准确的统计信息是执行计划正确的基本前提,6.8小时-->9秒
- 为准确生成执行计划更新统计信息-analyze与dbms_stats
- 为准确生成执行计划更新统计信息-analyze与dbms_stats
- 统计信息自动收集时间窗口导致分区表执行计划错误
- 直方图统计导致错误的执行计划
- 通过锁定统计信息来锁定执行计划
- Oracle的优化器是CBO,所以对象的统计数据对执行计划的生成至关重要
- 收集到较为直观和详细的执行计划和相关统计信息
- 修改统计信息改变执行计划(ORACLE)
- 集簇因子对执行计划影响和统计信息拷贝
- SQL Server 执行计划利用统计信息对数据行的预估原理二(为什么复合索引列顺序会影响到执行计划对数据行的预估)
- 6.2.3 收集执行计划统计信息
- SQL执行计划及统计信息相关视图
- 解决scott用户执行计划看不到统计信息的问题
- 10G之后统计信息收集后为什么执行计划不会被立马淘汰