20.集群因子(Clustering Factor)

发布时间 2023-08-27 20:45:33作者: 站在巨人的肩上Z

集群因子用于判断索引回表需要消耗的物理I/O次数。

这里在测试表test上创建一个索引:

create index idx_id on test(object_id);
select owner, index_name, clustering_factor  from dba_indexes where owner = 'TEST' and index_name = 'IDX_ID';

结果展示:

OWNER                INDEX_NAME           CLUSTERING_FACTOR
-------------------- -------------------- -----------------
TEST                 IDX_ID                            1597

索引idx_id的叶子块中有序地存储了索引的键值以及键值对应所在的Rowid.

SQL> select * from (select object_id, rowid  from test  where object_id is not null order by object_id) where rownum<=5;

 OBJECT_ID ROWID
---------- ------------------
         2 AAASACAAFAAAA0TAAi
         3 AAASACAAFAAAA0TAAJ
         4 AAASACAAFAAAA0TAAh
         5 AAASACAAFAAAA0TAAk
         6 AAASACAAFAAAA0TAAK

  首先我们比较 2、3 对应的 ROWID 是否在同一个数据块,如果在同一个数据块,Clustering Factor +0;如果不在同一个数据块,那么 Clustering Factor 值加 1。 然后我们比较 3、4 对应的 ROWID 是否在同一个数据块,如果在同一个数据块,Clustering Factor 值不变;如果不在同一个数据块,那么 Clustering Factor 值加 1。 接下来我们比较4、5对应的ROWID是否在同一个数据块,如果在同一个数据块,Clustering Factor +0;如果不在同一个数据块,那么 Clustering Factor 值加 1。 像上面步骤一样,一直这样有序地比较下去,直到比较完索引中最后一个键值。

   根据算法我们知道集群因子介于表的块数和表行数之间。 如果集群因子与块数接近,说明表的数据基本上是有序的,而且其顺序基本与索引顺序一 样。这样在进行索引范围或者索引全扫描的时候,回表只需要读取少量的数据块就能完成。 如果集群因子与表记录数接近,说明表的数据和索引顺序差异很大,在进行索引范围扫描 或者索引全扫描的时候,回表会读取更多的数据块。 集群因子只会影响索引范围扫描(INDEX RANGE SCAN)以及索引全扫描(INDEX FULL SCAN),因为只有这两种索引扫描方式会有大量数据回表集群因子不会影响索引唯一扫描(INDEX UNIQUE SCAN),因为索引唯一扫描只返回一 条数据。集群因子更不会影响索引快速全扫描(INDEX FAST FULL SCAN),因为索引快速全扫描不回表

查看一下表的总块数

SQL> select count(distinct dbms_rowid.rowid_block_number(rowid)) blocks from test.test;

    BLOCKS
----------
      1411

  再次强调一遍,在进行 SQL 优化的时候,往往会建立合适的组合索引消除回表,或者建 立组合索引尽量减少回表次数。如果无法避免回表,怎么做才能消除回表对 SQL 查询性能产生影响呢?当我们把表中所 有的数据块缓存在 buffer cache 中,这个时候不管集群因子多大,对 SQL 查询性能也没有多大 影响,因为这时不需要物理 I/O,数据块全在内存中访问速度是非常快的。