[转载]与索引相关的概念---聚簇因子

1、聚簇因子(Clustering factor)

 索引行的存储顺序与表中行的存储顺序之间的相似程度。

当相似度高时,这些数据行就会密集地存储在相对较少的数据块中,这是聚簇因子比较好的情况。

Oracle中,对于同一个查询语句,有时候会很快的完成,有时候却很慢,但是表结构什么的完全一致,表中的数据也完全一致,这个具体是什么原因呢,就要从Index中的细节说起了。

在Oracle中的一个特殊的视图user_indexes中有一个特殊的列,名字是clustering_factor,这个值的内容就是如果访问表的整个表数据,会造成多少次数据库IO。

A:如果这个值与块数接近,则说明表相当有序,得到了很好的组织。在这种情况下,同一个叶子块中的索引条目可能指向同一个数据块中的行。

B:如果这个值与行数接近,表的次序可能就是非常随机的。在这种情况下,同一个叶子块上的索引条目不太可能指向同一个数据块上的行。

可以把聚簇因子看作是通过索引读取整个表时对表执行的逻辑I/O次数。也就是说聚簇因子指示了表相对于索引本身的有序程度。当oracle对索引结构执行区间扫描时,如果它发现索引中的下一行与前一行在同一个数据块上,就不会再执行另一个I/O从缓冲区缓存中获得表块。它已经有了表块的一个句柄,只需要直接使用就行了。不过,如果下一行不在同一个块上,就会释放当前的这个块,而执行另一个物理I/O在缓冲区缓存存放要处理的下一个块。

另外还要记住:对于一个表来说,一般只有一个索引能够有合适的聚簇因子!表中的行可能只以一种方式排序。

我们可以通过下面的SQL语句来查看。

SELECT
        A.INDEX_NAME,
        B.NUM_ROWS,
        B.BLOCKS,
        A.CLUSTERING_FACTOR
FROM
        USER_INDEXES A,
        USER_TABLES B
WHERE
        A.INDEX_NAME = ?
        AND A.TABLE_NAME = B.TABLE_NAME

在这个SQL语句中,?代表的就是我们要检索的Index的名称。在表中数据有时候属于无序状态,这个时候的CLUSTERING_FACTOR比较接近NUM_ROWS,说明如果扫描整个表,每次都要根据Index来读取相应行的RowID,这个时候的IO操作很多,自然检索时间会比较长。如果数据有序的话,CLUSTERING_FACTOR比较接近BLOCKS,说明相邻的数据在一个块中,减少了IO操作数量,自然检索时间会大大降低。

下面这一段是Oracle 手册中关于CLUSTERING_FACTOR的说明:

Indicates the amount of order of the rows in the table based on the values of the index.

  • If the value is near the number of blocks, then the table is very well ordered. In this case, the index entries in a single leaf block tend to point to rows in the same data blocks.

  • If the value is near the number of rows, then the table is very randomly ordered. In this case, it is unlikely that index entries in the same leaf block point to rows in the same data blocks.

1、准备试验条件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
--创建表t_1
CREATE TABLE t_1
AS
SELECT ROWNUM rn,a.* FROM all_objects a ORDER BY object_name DESC;
  
--创建t_1表关于rownum索引
CREATE INDEX ind_t_1 ON t_1(rn);
  
--创建表表t_2
CREATE TABLE t_2
AS
SELECT * FROM (
SELECT ROWNUM rn,a.* FROM all_objects a ) ORDER BY rn ASC;
  
--创建t_2表关于rownum索引
CREATE INDEX ind_t_2 ON t_2(rn);
  
--分析两张表及其索引
EXEC DBMS_STATS.gather_table_stats(USER, 'T_1');
EXEC DBMS_STATS.gather_table_stats(USER, 'T_2');
EXEC DBMS_STATS.gather_index_stats(USER, 'IND_T_1');
EXEC DBMS_STATS.gather_index_stats(USER, 'IND_T_2');
  
--说明:两个表的区别就是t_2表中的rn是有序的,刚刚建立t_2表的索引一致

2、执行查询操作
SQL> set autot traceonly stat;
SQL> SELECT * FROM t_1 WHERE rn BETWEEN 100 AND 120;

已选择21行。

统计信息
———————————————————-
0 recursive calls
0 db block gets
17 consistent gets
0 physical reads
0 redo size
1807 bytes sent via SQL*Net to client
357 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
21 rows processed

SQL> SELECT * FROM t_2 WHERE rn BETWEEN 100 AND 120;

已选择21行。

统计信息
———————————————————-
0 recursive calls
0 db block gets
7 consistent gets
0 physical reads
0 redo size
1807 bytes sent via SQL*Net to client
357 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
21 rows processed

3、观察试验结果
通过执行统计信息观察,t_1表的查询一致读是17,而t_2表的一致读只有7,尽然t_1的一致读尽然是t_2的2倍还多,是不是有点奇怪,同样的表结构,同样的数据(t_2多两条数据)

4、分析原因
通过查询聚簇因子发现,两个表的聚簇因子差别很大,基于rn的索引在rn是顺序排列的表中,clustering_factor的值相差很大。
在表中数据有时候属于无序状态,这个时候的CLUSTERING_FACTOR比较接近NUM_ROWS,说明如 果扫描整个表,每次都要根据Index来读取相应行的RowID,这个时候的IO操作很多,自然检索时间会比较长。如果数据有序的 话,CLUSTERING_FACTOR比较接近BLOCKS,说明相邻的数据在一个块中,减少了IO操作数量,自然检索时间会大大降低。


 

posted @ 2011-11-08 15:21  刘竹青  阅读(147)  评论(0编辑  收藏  举报