A measure of the row order in>
The more order that exists in row storage for this value, the lower the clustering factor.
对于此值,行存储中存在的顺序越多,聚类因子越低。
索引idx_id的叶子块中有序的存储了索引的键值以及键值对应行所在的ROWID:
示例:
create table scott.test as select * from dba_object;
create index scott.idx_object_id on scott.test(object_id);
SCOTT@PROD>select owner,index_name,table_name,clustering_factor from dba_indexes where table_name='TEST';
OWNER INDEX_NAME TABLE_NAME CLUSTERING_FACTOR
SCOTT > SCOTT@PROD>select count(*) from scott.test;
COUNT(*)
75275
*** 索引idx_id的叶子块中有序的存储了索引的键值以及键值对应行所在的ROWID(默认情况下索引是升序的):
SCOTT@PROD> select * from (
2 select object_id, rowid
3 from test
4 where object_id is not null
5 order by object_id) where rownumselect sum(case
2 when block#1 = block#2 and file#1 = file#2 then
3 0
4 else
5 1
6 end) CLUSTERING_FACTOR
7 from (select dbms_rowid.rowid_relative_fno(rowid) file#1,
8 lead(dbms_rowid.rowid_relative_fno(rowid), 1, null) over(order by object_id) file#2,
dbms_rowid.rowid_block_number(rowid) block#1,
10 lead(dbms_rowid.rowid_block_number(rowid), 1, null) over(order by object_id) block#2
11 from test
12 where object_id is not null);
CLUSTERING_FACTOR
1192
和上面的一样
表的总块数为:
select count(distinct dbms_rowid.rowid_block_number(rowid)) blocks from scott.test;
SCOTT@PROD>select count(distinct dbms_rowid.rowid_block_number(rowid)) blocks from scott.test;
BLOCKS
1072
集群因子非常接近表的总块儿数的
实验:
set arraysize 5000
set autot trace
select * from scott.test where object_id < 1000;
SCOTT@PROD>select * from scott.test where object_id < 1000;
997 rows selected.
|* 2 | INDEX RANGE SCAN |>Predicate Information (identified by operation> 2 - access("OBJECT_ID" 92831 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
997 rows processed
解析:返回997条数据,(index range scan) 返回一条数据要回表一次,也就意味着要回表997次,但是逻辑读consistent gets(21个)
因为集群因子很小,所以它回表逻辑读很小。
实验:现在新建一个测试表test2,并且对数据随机排序:
create table scott.test2 as select * from scott.test order by dbms_random.value;
create index scott.idx_id2 on scott.test2(object_id);
查看idx_id2的集群因子:
select owner,index_name,table_name,clustering_factor from dba_indexes where owner='SCOTT' and table_name='TEST2';
SCOTT@PROD>select owner,index_name,table_name,clustering_factor from dba_indexes where owner='SCOTT' and table_name='TEST2';
OWNER INDEX_NAME TABLE_NAME CLUSTERING_FACTOR
SCOTT > 集群因子非常大,接近于表的总行数(75275)
再来看看相同的SQL,它的执行执行计划还有逻辑读...
set arraysize 5000
set autot trace
select * from scott.test2 where object_id < 1000;
SCOTT@PROD>set arraysize 5000
SCOTT@PROD>set autot trace
SCOTT@PROD>select * from scott.test2 where object_id < 1000;
997 rows selected.
Predicate Information (identified by operation> 1 - filter("OBJECT_ID" 71501 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
997 rows processed
请注意,不要尝试重建索引来降低集群因子,那根本没用,因为表中的数据顺序始终没变。 唯一能降低集群因子的办法就是根据索引列排序对表进行重建
(create table new_table as select * from old_table order by 索引列),但是这在实际操作中是不可取的,因为你无法照顾到每一个索引。