首页 > 数据库 > Oracle > oracle 聚簇因子及实验
什么是聚簇因子
聚簇因子是基于表上索引列上的一个值,每一个索引都有一个聚簇因子。
用于描述索引块上与表块上存储数据在顺序上的相似程度,也就说表上的数据行的存储顺序与索引列上顺序是否一致。
在全索引扫描中,CF的值基本上等同于物理I/O或块访问数,如果相同的块被连续读,则Oracle认为只需要1次物理I/O。
好的CF值接近于表上的块数,而差的CF值则接近于表上的行数。
聚簇因子在索引创建时就会通过表上存存在的行以及索引块计算获得。
1.clustering factor(聚簇因子)越低越好,会影响CBO的选择。
2.hint完比对物理读,如果走全表且物理读过高,建议还是走索引,调低聚簇因子。
3.随着时间,clustering factor总是趋势与不断恶化的
创建问题(怎么都不走索引,hint)
创建测试表jack
create table jack as select * from dba_objects where 1=2;
将数据无序的插入jack表中
begin for i in 1..10 loop insert /*+ append */ into jack select * from dba_objects order by i; commit; end loop; end; /
查询行数
select count(*) from jack;
查看一下表的大小
set wrap off col owner for a10; col segment_name for a15; select segment_name,blocks,extents,bytes/1024/1024||'M' "size" from dba_segments where segment_name='JACK';
在object_id上创建索引
create index jack_ind on jack(object_id);
查看一下索引的大小
select segment_name,segment_type,blocks,extents,bytes/1024/1024||'M' "size" from dba_segments where
segment_name='JACK_IND';
在没有收集相关的统计信息之前,查看一下index clustering factor
select index_name,clustering_factor,num_rows from dba_indexes where index_name='JACK_IND';
简单的收集一下统计信息
exec dbms_stats.gather_table_stats(user,'jack',cascade=>true);
再次查看index clustering factor
select index_name,clustering_factor,num_rows from dba_indexes where index_name='JACK_IND';
----显然统计信息收集前和后,clustering factor值不变,说在创建索引的时候,会收集表中的数据真正的行数。
并且这里的clustering factor等num_rows,也说明表的clustering factor是无序的。
查看一个确定值,然后查看执行计划
explain plan for select * from jack where object_id=1501;
select * from table(dbms_xplan.display);
--走了索引,cost13
清空buffer cache(当前为测试,生产千万别做)
alter system flush buffer_cache;
取一个查范围的执行计划
set autotrace traceonly;
select * from jack where object_id>1000 and object_id<2000;
--不走索引,走的全表扫描
清空buffer cache(当前为测试,生产千万别做)
alter system flush buffer_cache;
强制走索引,查看执行计划
select /*+ index(jack jack_ind) */ * from jack where object_id>1000 and object_id<2000;
----强制走索引之后,使用了index range scan,但是cost变成了9683,而全表扫描时是1824.
----还有比较一下两次查询中物理读的情况:全表扫描的物理读明显比索引的要高很多,但是Oracle却没有使用索引。
----因此Oracle认为走索引的Cost比走全表扫描大,而是大N倍,CBO是基于Cost来决定执行计划的。
----由此得出,对于索引的Cost,Oracle是根据clustering factor参数来计算的,而该实验中的clustering factor参数
是很高的,数据存储无序。这就造成了Oracle认为走索引的cost比全表扫描的大。
两种思路(1.聚簇因子方面 2.块方面):
1.方法一(推荐)
调整聚簇因子
exec dbms_stats.set_index_stats(ownname => 'DEF',indname => 'JACK_IND',clstfct => 600000);
select index_name,clustering_factor,num_rows from dba_indexes where index_name='JACK_IND';
聚簇因子接近块数好,约小会比较好。无绝对。
查看表存储块数
select sum(blocks) from dba_tables where table_name='JACK' and owner='DEF';
查看表行数
select count(*) from def.jack;
2.方法二(调整聚簇因子)(收益很小)
对索引进行rebuild
alter index jack_ind rebuild;
不一定能解决问题,因为索引通常是有序的,一般无序的是表上的数据
3.方法三(调整表的块)(推荐)
定期重构堆表,使表与索引上的数据顺序更加接近
create table tmp_article_info as select * from article_info;
or
在线重定义
4.方法四
使用聚簇表
1.表dml操作后,收集统计信息才能查看最新的聚簇因子。
2.alter table move tabname并不会影响CF的值,该功能只是移动高水位线,且不释放空间。
3.重建索引对CF的值收效甚微,因为原始表数据存储顺序未发生根本变化。
4.CF的值是影响查询分析器对执行计划的评估与生成的因素之一(即是否走索引还是全表扫描,嵌套连接
时哪个表为驱动表等)
参考:
部分内容参考Leshami
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69980685/viewspace-3004609/ ,如需转载,请注明出处,否则将追究法律责任。