预备知识:
索引是针对于列提出来的概念。
假设对object_id建立索引,就要将这一列的‘值’和‘rowid’一起放到索引中去。rowid就是表中某一行的物理地址(rowid=数据文件号+块号 【一个extent中rowid的值是递增的】)。
Oracle中表是堆表,表中的数据是无序的,但是索引中的数据是排序的。索引排序是根据键值来排序的。
集群因子是针对于索引提出来的概念。
集群因子:
集群因子是什么?集群因子是怎么算出来的?
索引中存放的是键值+rowid,我们来模拟一个索引的结构:
集群因子:
从排好序的第一行开始,clustering=0
第二行如果和第一行在同一个块中,clustering=0
第三行如果到了第二个块中,clustering=1
第四行如果和第三行在同一个块中,clustering=1
第五行和第四行相比如果又到了另外一个块中,clustering=2
第六行和第五行相比如果又到了另外一个块中,clustering=3
以此类推,直到最后一个块为止。。。
这就是集群因子。
下面的sql能得到每一行的数据文件号、块号:
select
object_id,
dbms_rowid.rowid_relative_fno(rowid) file#,
dbms_rowid.rowid_block_number(rowid) block#,
dbms_rowid.rowid_row_number(rowid) row#
from test where rownum < 20 order by object_id;
集群因子介于表的总行数和表的总块数之间。
集群因子越接近于总行数,说明列在表中分布的很散乱。
集群因子越接近于总块数,说明列在表中的分布很集中,相当于是排过序的。
例如 select * from test where object_id < 1000 这个sql走索引的话需要回表,
最理想的情况下, 2,3,4 .... 999所在的行都在同一个块中,这时候只需要把一个块读到buffer中,只有第一次回表需要物理IO,之后的回表都是逻辑IO
最糟糕的情况下,2,3,4 。。。 999 所在的行都在不同的块中,这时候每次回表都需要将不同的块读取到buffer中,发生物理IO
集群因子的作用:
集群因子是用来衡量 通过索引回表需要多少物理IO的。
怎么消除集群因子的影响呢?
1、把整个的表都放在buffer cache中
2、集群因子对返回数据少的条件没有影响
3、集群因子影响的时范围扫描。
怎么改变集群因子:
由于一张表中,我们经常在多个列上简历索引,改善了一个索引的集群因子,很有可能导致另外一个索引的集群因子变得更差,因此集群因子基本上是无解的。
既然集群因子是无解的,我们为什么还要了解他呢?
这就涉及到了sql优化的核心思想,sql优化的核心思想就是<<<减少物理IO的扫描次数>>>。
怎么得到一个索引的集群因子:
select index_name,clustering_factor from user_indexes;
原文地址:https://www.cnblogs.com/nathon-wang/p/10332209.html