zoukankan      html  css  js  c++  java
  • [转载]与索引相关的概念聚簇因子

    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操作数量,自然检索时间会大大降低。


     

  • 相关阅读:
    设计一个圆柱体类,计算表面积及体积。建立一个半径为3、高为3.5的圆柱体,输出其表面积及体积
    写一个方法完成如下功能,判断从文本框textbox1输入的一个字符,如果是数字则求该数字的阶乘,如果是小写字条,则转换为大写,大写字符不变,结果在文本框textbox2中显示
    写一方法用来计算1+2+3+...n,其中n作为参数输入,返回值可以由方法名返回,也可以由参数返回
    winform控件记录
    写4个同名方法,实现两个整数、两个实数,一个实数一个整数,一个整数一个实数之间的求和。在主调函数中调用这4个方法计算相关的值。(方法的重载)
    写一方法计算实现任意个整数之和.在主调函数中调用该函数,实现任意个数之和。(使用params参数)
    在主函数中提示用户输入用户名和密码。另写一方法来判断用户输入是否正确。该方法分别返回一个bool类型的登录结果和和一个string类型的登录信息。如登录成功,返回true及“登录成功”,若登录失败则返回false及“用户名错误”或“密码错误”(使用out参数)
    Linux下使用Kickstart自动化安装平台架构
    Day10 多线程理论 开启线程
    关闭ipv6的方法
  • 原文地址:https://www.cnblogs.com/liuzhuqing/p/7480973.html
Copyright © 2011-2022 走看看