11g 等频直方图下sql不走索引扫描

[复制链接]
查看11 | 回复3 | 2011-2-18 11:43:34 | 显示全部楼层 |阅读模式
昨天下午开发人员报告一条非常奇怪的sql,使用该sql的执行计划使用全部扫描,但是查询列是建有索引的,oracle版本 11.2.0.2
该sql格式如下select * from doc_JUSTIN where do_no ='0069325106';
当时第一反应是该列数据分布不均匀,但是查询后发现该列选择性极佳
SQL> select count(*),count(distinct do_no) from doc_JUSTIN;
COUNT(*) COUNT(DISTINCTDO_NO)
---------- --------------------
14037996
14037996
检查统计信息,表和索引都是最近收集的,且该索引并没有失效,这就比较奇怪了;
使用autotrace查看执行计划
SQL> set autotrace traceonly
SQL> select * from doc_JUSTIN where do_no ='0069325106';
Execution Plan
----------------------------------------------------------
Plan hash value: 1702056455
-----------------------------------------------------------------------------------
| Id| Operation | Name
| Rows| Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT|
|7047K|2177M| 175K(1)| 00:35:07 |
|*1 |TABLE ACCESS FULL| DOC_JUSTIN|7047K|2177M| 175K(1)| 00:35:07 |
-----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("DO_NO"='0069325106')
Statistics
----------------------------------------------------------

1recursive calls

0db block gets
643568consistent gets

0physical reads

0redo size
7434bytes sent via SQL*Net to client
519bytes received via SQL*Net from client

2SQL*Net roundtrips to/from client

0sorts (memory)

0sorts (disk)
1 rows processed
添加hint,强制走索引,虽然consistent gets值下降为5,但是rows却为7047K,和全表扫描的一样,看来应是CBO的问题了
SQL> select /*+ index(doc_JUSTIN,IDX_JUSTIN_2) */ * from doc_JUSTIN where do_no ='0069325106';
Execution Plan
----------------------------------------------------------
Plan hash value: 1340941743
-----------------------------------------------------------------------------------------------
| Id| Operation
| Name
| Rows| Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT
|
|7047K|2177M| 961K(1)| 03:12:19 |
| 1 |TABLE ACCESS BY INDEX ROWID| DOC_JUSTIN|7047K|2177M| 961K(1)| 03:12:19 |
|*2 | INDEX RANGE SCAN
| IDX_JUSTIN_2|7047K| | 19027 (1)| 00:03:49 |
-----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("DO_NO"='0069325106')
Statistics
----------------------------------------------------------

1recursive calls

0db block gets

5consistent gets

0physical reads

0redo size
7441bytes sent via SQL*Net to client
519bytes received via SQL*Net from client

2SQL*Net roundtrips to/from client

0sorts (memory)

0sorts (disk)

1rows processed
使用10053跟踪一把
另:11g后的生成的跟踪文件跟10g变化很大,不再是生成以pid为标志的文件,可以通过查询v$diag_info获取生成的跟踪文件。
以下是10053的摘录,CBO通过计算比较,发现使用全表扫描的cost要比索引扫描小,所以选择全表扫描;
但是density居然为0.5,这是一个非常错误的值,而oracle是如何得来的?
***********************
Table Stats::
Table: DOC_JUSTINAlias: DOC_JUSTIN
#Rows: 14094996#Blks:644512AvgRowLen:324.00ChainCnt:0.00
Index Stats::
Index: IDX_JUSTIN_1Col#: 78
LVLS: 2#LB: 33266#DK: 56LB/K: 594.00DB/K: 11395.00CLUF: 638142.00
Index: IDX_JUSTIN_2Col#: 2
LVLS: 2#LB: 38100#DK: 14114520LB/K: 1.00DB/K: 1.00CLUF: 1923680.00
Index: IDX_JUSTIN_3Col#: 45
LVLS: 0#LB: 0#DK: 0LB/K: 0.00DB/K: 0.00CLUF: 0.00
Index: IDX_JUSTIN_4Col#: 34 5 3
LVLS: 2#LB: 46950#DK: 78LB/K: 601.00DB/K: 8181.00CLUF: 638147.00
Index: PK_DOC_JUSTINCol#: 1
LVLS: 2#LB: 28243#DK: 14134692LB/K: 1.00DB/K: 1.00CLUF: 668126.00
Access path analysis for DOC_JUSTIN
***************************************
SINGLE TABLE ACCESS PATH
Single Table Cardinality Estimation for DOC_JUSTIN[DOC_JUSTIN]
Column (#2):
NewDensity:0.500000, OldDensity:0.000000 BktCnt:5548, PopBktCnt:5548, PopValCnt:1, NDV:205
Column (#2): DO_NO(
AvgLen: 11 NDV: 205 Nulls: 0 Density: 0.500000
Histogram: Freq#Bkts: 1UncompBkts: 5548EndPtVals: 1
Using density: 0.500000 of col #2 as selectivity of unpopular value pred
Table: DOC_JUSTINAlias: DOC_JUSTIN
Card: Original: 14094996.000000Rounded: 7047498Computed: 7047498.00Non Adjusted: 7047498.00
Access Path: TableScan
Cost:175559.75Resp: 175559.75Degree: 0
Cost_io: 174557.00Cost_cpu: 20094349137
Resp_io: 174557.00Resp_cpu: 20094349137
Using density: 0.500000 of col #2 as selectivity of unpopular value pred
Access Path: index (AllEqRange)
Index: IDX_JUSTIN_2
resc_io: 980892.00resc_cpu: 22017327324
ix_sel: 0.500000ix_sel_with_filters: 0.500000
Cost: 981990.71Resp: 981990.71Degree: 1
Best:: AccessPath: TableScan
Cost: 175559.75Degree: 1Resp: 175559.75Card: 7047498.00Bytes: 0
Google一把,找到一篇非常好的参考文档
http://www.adellera.it/investigations/11g_newdensity/11gNewDensity.pdf
原来从11.1.0.6开始,当有直方图时,CBO开始使用新算法计算density,不再使用数据字典dba_tab_columns中储存的density值;
该功能由隐含参数_optimizer_enable_density_improvements决定,当为true时开启
当为等频直方图时,newdensity = 0.5/numrows,但是该表有千万条数据,按说newdensity值应该非常小才对,不知为何会计算出值为0.5;
这应该是导致sql选择全表扫描的原因。
解决方案应该很简单,要么去除该列上的直方图信息,要么设置_optimizer_enable_density_improvements为false;
本来是说要今早执行的,但是早上来到后开发说问题已经解决了,他们把该表drop重建,此时表中只有几十万条记录,可以自动选择索引;
登录数据库检查一下,该列上的等频直方图已经消失, 失去了一个验证的好机会

回复

使用道具 举报

千问 | 2011-2-18 11:43:34 | 显示全部楼层
I suffer pains each time upgrade db to 11gr2 together with statistics updated.
too bad to see only one note in metalink to mention this hidden parameter without explanation. Oracle should treat this as something like "behavior change" and document it clearly.
thanks for the info, will look into my issues.
回复

使用道具 举报

千问 | 2011-2-18 11:43:34 | 显示全部楼层
SQL> SELECT JOB_NAME, SCHEDULE_NAME, SCHEDULE_TYPE, ENABLED
2FROM DBA_SCHEDULER_JOBS
3WHERE PROGRAM_NAME = 'GATHER_STATS_PROG';
怀疑自动搜集统计信息的job采样收集统计信息时恰好得到了错误的信息
回复

使用道具 举报

千问 | 2011-2-18 11:43:34 | 显示全部楼层
本帖最后由 Yong Huang 于 2011-9-30 08:26 编辑
Thanks for sharing. Very interesting. The parameter _optimizer_enable_density_improvements actually first appears in 10.2.0.4, not 11.1.0.6. But it's false in 10.2.0.4 and true in later versions. So if you plan to upgrade from 10.2.0.4 to 11g and want to see if a SQL will be affected by this new feature, you can change the value to true before the upgrade and test the SQL.
MOS articles
Oracle 11gR2 Upgrade Companion [Document 785351.1]
Oracle 11gR1 Upgrade Companion [Document 601807.1]
briefly talk about the new density feature:
"New density calculation (Oracle9i to Oracle Database 10g)
There is a new algorithm to calculate density in Oracle Database 10g Release 2 when histograms are present on the columns. This shows up in the 10053 traces as NewDensity.This will affect cardinality ESTIMATE calculations. The NewDensity is not stored in the data dictionary.The old density values are stored in data dictionary.NewDensity is calculated at run time."
You can find a few interesting articles on Google or MOS using keyword "newdensity" (no space in the middle).
Yong Huang
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行