在实际的系统中,目标列的数据分布有可能极度倾斜的。对于这样的列,如果还用均匀分布的原则计算可选择率,进而计算cardinality,然后再计算成本,最后选择执行计划,那么这个执行计划肯定是有问题的,因为在第一步计算的时候,就已经错了。
下面举个例子模拟下场景:
-
create table t1 (a number(5),b varchar2(5));
-
-
-
-
declare
-
cnt number(5) := 1;
-
begin
-
loop
-
insert into t1 values (1,1);
-
if cnt=10000 then
-
exit;
-
end if;
-
cnt :=cnt+1;
-
end loop;
-
insert into t1 values (2,2);
-
commit;
-
end;
create index t1_ix_b on t1(b);
在b上创建索引。
-
begin
-
dbms_stats.gather_table_stats('MEPF_DEV','T1',estimate_percent => 100,method_opt => 'for all columns size 1');
-
end;
for all colums size 1表示不收集直方图。
运行如下语句:
-
select count(*) from t1 where b='2';
-
select *
-
from dba_tab_col_statistics T
-
where table_name = 'T1'
-
AND column_name = 'B';

都显示直方图没有收集。
因为没有直方图,oracle默认,数据在该列的分布是均匀分布的,对该列实行等值查询的时候,用到的公式计算结果如下:

根据这个基数,oracle下面会计算各种执行计划的cost,此返回的基数已经占了总数据量的一般了,如果用index range scan则消耗的io代价很高。index fast full scan 和table access full 两个方式都是离散度,但是索引的块比较密,所以就用了index fast full scan。
评估一开始就错了,结果也就错了。
直方图就是为了解决上面的问题而存在的。它也是一种列的统计信息,直方图实际上存储在数据字典基表 HISTGRM$中,可以通过数据字典DBA_TAB_HISTOGRAMS,DBA_PART_HISTOGRAMS,DBA_SUBPART_HISTOGRAMS来分别查看表,分区表,分区表的子分区的直方图统计信息。
-
begin
-
dbms_stats.gather_table_stats('MEPF_DEV',
-
'T1',
-
estimate_percent => 100,
-
method_opt => 'for columns size auto b');
-
end;
收集下直方图。

列b上已经有了直方图的信息。
此时再次运行下该语句。
如果对目标列收集了直方图,则意味着cbo将不在默认数值在该目标列上是均匀分布的了,CBO会用该目标列上的直方图统计信息来计算对该列施加
查询条件后的可选则率和返回结果集的cardinality,进而根据基数算出成本,选择相应的执行计划。
那么直方图有哪几种类型呢,直方图是怎么影响cbo的计算呢,下一节会详细讲述。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/30109892/viewspace-1828943/
,如需转载,请注明出处,否则将追究法律责任。