CBO学习----03--选择率(Selectivity)(一)

2014-11-24 15:58:20 · 作者: · 浏览: 7
CBO学习----03--选择率(Selectivity)
CBO学习---第2章--表扫描(Tablescans)
http://www.2cto.com/database/201307/229069. html
第3章 单表选择率(Single Table Selectivity)
Selectivity是优化器估算Rows(Cards)的重要依据。
/**************************************************************************************************************************************/
3.1 Getting Started
select count(*)
from audience
where month_no = 12
;

从优化器的角度,分析1200名听众中,估算12月出生的人数
(1)user_tab_col_statistics.num_distinct=12
(2)user_tab_histograms指出low(1),high(12),均匀分布
(3)user_tab_col_statistics.density=1/12
(4)month_no=12,单列,均一,所以user_tab_col_statistics.density可用
(5)low(1)<=12<=high(12)
(6)user_tab_col_statistics.num_nulls=0,没有空值
(7)user_tables.num_rows=1200
(8)1200/12=100
本章代码附件中:
birth_month_01.sql
hack_stats.sql
birth_month_01.sql构建表,先进行两次查询系统表,后做count(*)查询两次。
两次之间可在其他session执行hack_stats.sql,修改表的统计信息,看哪些统计项能影响rows的计算
(1)将表名和列名填入hack_stats.sql,并修改表的行数numrows
[sql] 
define m_source_table='AUDIENCE'  
define m_source_column='month_no'  
--m_avgrlen := m_avgrlen + 25;  
m_numrows:=m_numrows+1200;  

交叉执行后,rows从100变成200
测试后将numrows复原
(2)修改distcnt和density
打开Column statistics的注释
[sql] 
--m_distcnt:=m_distcnt+12;  
m_density:=m_density/2;  

经多次测试,distcnt的修改不起作用,说明仅有density参与计算( Oracle版本10204)。
并非像书中所提的那样,可能9i和10gR1中,没有直方图时是用distcnt来计算rows,Oracle之后的版本又改进了
测试后将density复原
/**************************************************************************************************************************************/
[sql] 
begin  
    dbms_stats.gather_table_stats(  
        user,  
        'audience',  
        cascade => true,  
        estimate_percent => null,  
        method_opt => 'for all columns size 1'  
    );  
end;  
/  

其中method_opt => 'for all columns size 1',指不收集直方图,8i和9i的默认值
method_opt =>'for all columns size auto'10g默认值,可以通过下面方法读取
[sql] 
SQL> select dbms_stats.get_param('METHOD_OPT') from dual;  
  
  
DBMS_STATS.GET_PARAM('METHOD_OPT')  
---------------------------------------------------------  
FOR ALL COLUMNS SIZE AUTO  
  
  
已选择 1 行。  

/**************************************************************************************************************************************/

3.2 Null Values
将null加入到rows的计算中
假定10%的人不记得自己的生日在几月
本章代码附件中:
birth_month_02.sql
该脚本中,将120行设置为空值,最终rows=90
说明优化器排除了null对估算rows的影响;density依然是1/12,并没有改变,说明density是减去空值数量后的结果。
/**************************************************************************************************************************************/
3.3 Using Lists
select count(*)
from audience
where month_no in (6,7,8)
;

开始研究month_no in (6,7,8),这种条件时,rows的计算方式
本章代码附件中:
in_list.sql
在没有重复值时,rows计算无误
/**************************************************************************************************************************************/
8i中计算错误的原因:
select count(*) from audience where month_no in (6,7,8);
select /* +use_concat */count(*) from audience where month_no in (6,7,8);


/****************************************************************************************************