zoukankan      html  css  js  c++  java
  • 详解oracle bitmap位图索引

    zt http://f.dataguru.cn/thread-226223-1-2.html

    位图索引是oracle中非常重要的一种索引形式。本文通过总结有关位图索引的资料,尝试回答如下几个问题:

    1:什么是位图索引?

    2:位图索引适合什么场景,不适合什么场景?

    3:位图索引的性能如何?


    什么是位图索引?

    位图索引,顾名思义,与“位”有关。大家都知道,计算机中的所有信息最终都是通过“位bit”来运算的, 二进制位运算在计算机中是非常高效的。每一个二进制位都可以取值0或者1,而取值的确切含义是由具体的上下文环境决定的。在oracle位图索引中,每一个二进制位代表了某一行中索引列的取值情况。例如,学生表中性别列的位图索引结构如下:

    男:0101001101

    女:1010110010

    在上面的位图结构中,存储了10条学生记录的性别分布情况,以“男”性别为例,从左到右的第n个二进制位代表了第n条记录是否性别为男,如果二进制位为1,代表true即性别为男,0代表false即性别不为男。以此类推,从图中可以看出,第一条记录的性别为女,第二条记录的性别为男,...第九条记录的性别为女,第十条记录的性别为男。

    大家都知道,在oracle中是根据rowid来定位记录的,因此,我们需要引入start rowid和end rowid,通过start rowid ,end rowid 和二进制位的偏移,我们就可以非常快速的计算出二进制位所代表的表记录rowid。位图索引的最终逻辑结构如下图:


    位图索引适合什么场景,不适合什么场景?现在我们已经了解了位图索引的逻辑结构,我们称每一单元的<key ,startrowid,end rowid,bitmap>为一个位图片段。当我们修改某一行数据的时候,我们需要锁定该行列值所对应的位图片段,如果我们进行的是更新操作,同时还会锁定更新后新值所在的位图片段。例如我们将列值从01修改为03,就需要同时锁定01和03位图片段,此时如果有其他用户需要修改与01或者03关联的表记录上的索引字段,就会被阻塞,因此位图索引不适合并发环境,在并发环境下可能会造成大量事务的阻塞。

    从位图索引的逻辑结构也可以看出,当索引列的distinct cardinality较大时,索引所占用的存储空间也会成比例扩大。下面我们测试一下位图索引占用空间与distinct cardinality的关系:
    数据库环境:oracle 11g  
    数据块大小:8k
    [sql] view plaincopyprint?


    • CREATE or replace FUNCTION ind_spc_test(rn NUMBER) RETURN NUMBER  
    •   AS  
    •       v_j     NUMBER;  
    •       v_dis   NUMBER;  
    •       v_bm_sp NUMBER;  
    •       v_bt_sp NUMBER;  
    •     BEGIN  
    •       FOR i IN 1 .. 10LOOP  
    •         EXECUTE immediate 'truncate table t_easy1';  
    •         EXECUTE immediate 'truncate table t_easy2';  
    •         SELECT floor(rn/(11-i)) INTO v_j FROM dual;  
    •         FOR j IN 1 .. rn LOOP  
    •           INSERT INTO t_easy1 VALUES (mod(j,v_j));  
    •           INSERT INTO t_easy2 VALUES (mod(j,v_j));  
    •         END LOOP;  
    •         commit;  
    •         select count(distinct id) into v_j from t_easy1;  
    •         EXECUTE immediate 'analyze index i_easy1 COMPUTE STATISTICS';  
    •         SELECT lEAF_BLOCKS INTO v_bt_sp FROM user_indexes where index_name='I_EASY1';  
    •         EXECUTE immediate 'analyze index i_easy2 COMPUTE STATISTICS';  
    •         SELECT LEAF_BLOCKS INTO v_bm_sp FROM user_indexes where index_name='I_EASY2';  
    •         INSERT INTO bitmap_ind_space VALUES (v_j,v_bm_sp,v_bt_sp,rn );  
    •         COMMIT;  
    •       END LOOP;  
    •       RETURN 0;  
    •     END;  



    [sql] view plaincopyprint?


    • SQL> select * from bitmap_ind_space order by 1;  
    •   
    • DISTINCT_VAL BITMAP_IND_BLKS BTREE_IND_BLKS    ROW_NUM  
    • ------------ --------------- -------------- ----------  
    •        10000         139        300 100000  
    •        11111          79        335 100000  
    •        12500          89        285 100000  
    •        14285         103        220 100000  
    •        16666         120        257 100000  
    •        20000         146        310 100000  
    •        25000         183        293 100000  
    •        33333         246        262 100000  
    •        50000         371        296 100000  
    •       100000         408        200 100000  



    这里的测试比较简单,下面看看大师的实验结果:




    从这里可以看出,随着distinct columns值的增加,位图索引占用空间逐步增大,但即便在最坏的情况下,位图索引占用的空间也仅仅是普通索引的2~3倍,在存储日益普遍的今天,这恐怕并不是很大的问题。

    位图索引的查询性能如何?下面我们看一下位图索引的查询性能如何。
    在很多资料中,都可以看到这样的论述:位图索引适合于 low distict cardinality的列。实际上,对于high distinct cardinality 的列,位图索引的查询性能也是非常不错的。下面我们来验证这个结论。
    首先我们创建两张表:emp_normal和emp_random.
    [sql] view plaincopyprint?


    • SQL> create table emp_normal(empno number(10), ename varchar2(30), sal number(10));  
    •   
    • 表已创建。  
    •   
    • Begin  
    • For i in 1..1000000  
    • Loop  
    •    Insert into emp_normal   
    •    values(i, dbms_random.string('U',30), dbms_random.value(1000,7000));  
    •    If mod(i, 10000) = 0 then  
    •    Commit;  
    •   End if;  
    • End loop;  
    • 10  End;  
    • 11  /  
    •   
    • PL/SQL 过程已成功完成。  
    •   
    • SQL> create table emp_random as select /* +append */ * from emp_normal order by dbms_random.random;  


    emp_random由于其记录是随机分布的,因此该表上索引的CLUSTERING_FACTOR要高一些。
    我们首先看一下emp_normal表等值查询情况下,索引的效率如何:
    [sql] view plaincopyprint?


    • SQL> create bitmap index bm_normal on emp_normal(empno);  
    •   
    • 索引已创建。  
    •   
    •   
    • SQL> analyze table emp_normal compute statistics for table for all indexes for all indexed columns;  
    •   
    • 表已分析。  
    •   
    • SQL> select index_name,clustering_factor from user_indexes;  
    •   
    • INDEX_NAME             CLUSTERING_FACTOR  
    • ------------------------------ -----------------  
    • BM_NORMAL                1000000  
    •   
    • SQL> set autot traceonly  
    • SQL> select * from emp_normal where empno=&empno;  
    • 输入 empno 的值:  1000  
    • 原值    1: select * from emp_normal where empno=&empno  
    • 新值    1: select * from emp_normal where empno=1000  
    •   
    •   
    • 执行计划  
    • ----------------------------------------------------------  
    • Plan hash value: 1526426521  
    •   
    • -------------------------------------------------------------------------------------------  
    • | Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time     |  
    • -------------------------------------------------------------------------------------------  
    • |   0 | SELECT STATEMENT         |        | 1 |    34 | 3   (0)| 00:00:01 |  
    • |   1 |  TABLE ACCESS BY INDEX ROWID | EMP_NORMAL | 1 |    34 | 3   (0)| 00:00:01 |  
    • |   2 |   BITMAP CONVERSION TO ROWIDS|        |   |   |        |      |  
    • |*  3 |    BITMAP INDEX SINGLE VALUE | BM_NORMAL  |   |   |        |      |  
    • -------------------------------------------------------------------------------------------  
    •   
    • Predicate Information (identified by operation id):  
    • ---------------------------------------------------  
    •   
    •    3 - access("EMPNO"=1000)  
    •   
    •   
    • 统计信息  
    • ----------------------------------------------------------  
    •       1  recursive calls  
    •       0  db block gets  
    •       5  consistent gets  
    •       0  physical reads  
    •       0  redo size  
    •     702  bytes sent via SQL*Net to client  
    •     520  bytes received via SQL*Net from client  
    •       2  SQL*Net roundtrips to/from client  
    •       0  sorts (memory)  
    •       0  sorts (disk)  
    •       1  rows processed  
    •   
    • SQL> select * from emp_normal where empno=&empno;  
    • 输入 empno 的值:  2398  
    • 原值    1: select * from emp_normal where empno=&empno  
    • 新值    1: select * from emp_normal where empno=2398  
    •   
    •   
    • 执行计划  
    • ----------------------------------------------------------  
    • Plan hash value: 1526426521  
    •   
    • -------------------------------------------------------------------------------------------  
    • | Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time     |  
    • -------------------------------------------------------------------------------------------  
    • |   0 | SELECT STATEMENT         |        | 1 |    34 | 3   (0)| 00:00:01 |  
    • |   1 |  TABLE ACCESS BY INDEX ROWID | EMP_NORMAL | 1 |    34 | 3   (0)| 00:00:01 |  
    • |   2 |   BITMAP CONVERSION TO ROWIDS|        |   |   |        |      |  
    • |*  3 |    BITMAP INDEX SINGLE VALUE | BM_NORMAL  |   |   |        |      |  
    • -------------------------------------------------------------------------------------------  
    •   
    • Predicate Information (identified by operation id):  
    • ---------------------------------------------------  
    •   
    •    3 - access("EMPNO"=2398)  
    •   
    •   
    • 统计信息  
    • ----------------------------------------------------------  
    •       1  recursive calls  
    •       0  db block gets  
    •       5  consistent gets  
    •       0  physical reads  
    •       0  redo size  
    •     703  bytes sent via SQL*Net to client  
    •     520  bytes received via SQL*Net from client  
    •       2  SQL*Net roundtrips to/from client  
    •       0  sorts (memory)  
    •       0  sorts (disk)  
    •       1  rows processed  
    •   
    • SQL> select * from emp_normal where empno=&empno;  
    • 输入 empno 的值:  8545  
    • 原值    1: select * from emp_normal where empno=&empno  
    • 新值    1: select * from emp_normal where empno=8545  
    •   
    •   
    • 执行计划  
    • ----------------------------------------------------------  
    • Plan hash value: 1526426521  
    •   
    • -------------------------------------------------------------------------------------------  
    • | Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time     |  
    • -------------------------------------------------------------------------------------------  
    • |   0 | SELECT STATEMENT         |        | 1 |    34 | 3   (0)| 00:00:01 |  
    • |   1 |  TABLE ACCESS BY INDEX ROWID | EMP_NORMAL | 1 |    34 | 3   (0)| 00:00:01 |  
    • |   2 |   BITMAP CONVERSION TO ROWIDS|        |   |   |        |      |  
    • |*  3 |    BITMAP INDEX SINGLE VALUE | BM_NORMAL  |   |   |        |      |  
    • -------------------------------------------------------------------------------------------  
    •   
    • Predicate Information (identified by operation id):  
    • ---------------------------------------------------  
    •   
    •    3 - access("EMPNO"=8545)  
    •   
    •   
    • 统计信息  
    • ----------------------------------------------------------  
    •       1  recursive calls  
    •       0  db block gets  
    •       5  consistent gets  
    •       0  physical reads  
    •       0  redo size  
    •     703  bytes sent via SQL*Net to client  
    •     520  bytes received via SQL*Net from client  
    •       2  SQL*Net roundtrips to/from client  
    •       0  sorts (memory)  
    •       0  sorts (disk)  
    •       1  rows processed  
    •   
    • SQL> select * from emp_normal where empno=&empno;  
    • 输入 empno 的值:  128444  
    • 原值    1: select * from emp_normal where empno=&empno  
    • 新值    1: select * from emp_normal where empno=128444  
    •   
    •   
    • 执行计划  
    • ----------------------------------------------------------  
    • Plan hash value: 1526426521  
    •   
    • -------------------------------------------------------------------------------------------  
    • | Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time     |  
    • -------------------------------------------------------------------------------------------  
    • |   0 | SELECT STATEMENT         |        | 1 |    34 | 3   (0)| 00:00:01 |  
    • |   1 |  TABLE ACCESS BY INDEX ROWID | EMP_NORMAL | 1 |    34 | 3   (0)| 00:00:01 |  
    • |   2 |   BITMAP CONVERSION TO ROWIDS|        |   |   |        |      |  
    • |*  3 |    BITMAP INDEX SINGLE VALUE | BM_NORMAL  |   |   |        |      |  
    • -------------------------------------------------------------------------------------------  
    •   
    • Predicate Information (identified by operation id):  
    • ---------------------------------------------------  
    •   
    •    3 - access("EMPNO"=128444)  
    •   
    •   
    • 统计信息  
    • ----------------------------------------------------------  
    •       1  recursive calls  
    •       0  db block gets  
    •       5  consistent gets  
    •       0  physical reads  
    •       0  redo size  
    •     704  bytes sent via SQL*Net to client  
    •     520  bytes received via SQL*Net from client  
    •       2  SQL*Net roundtrips to/from client  
    •       0  sorts (memory)  
    •       0  sorts (disk)  
    •       1  rows processed  
    •   
    • SQL> drop index bm_normal;  
    •   
    • 索引已删除。  
    •   
    • SQL> create index bt_normal on emp_normal(empno);  
    •   
    • 索引已创建。  
    •   
    • SQL> analyze table emp_normal compute statistics for table for all indexes for all indexed columns;  
    •   
    • 表已分析。  
    •   
    • SQL> select index_name,clustering_factor from user_indexes;  
    •   
    • INDEX_NAME             CLUSTERING_FACTOR  
    • ------------------------------ -----------------  
    • BT_NORMAL                   6210  
    • SYS_IL0000076897C00002$$  
    • PK_EMP                         1  
    • PK_DEPT                        1  
    •   
    • SQL> set autot traceonly  
    • SQL> select * from emp_normal where empno=&empno;  
    • 输入 empno 的值:  1000  
    • 原值    1: select * from emp_normal where empno=&empno  
    • 新值    1: select * from emp_normal where empno=1000  
    •   
    •   
    • 执行计划  
    • ----------------------------------------------------------  
    • Plan hash value: 733975378  
    •   
    • ------------------------------------------------------------------------------------------  
    • | Id  | Operation           | Name   | Rows  | Bytes | Cost (%CPU)| Time     |  
    • ------------------------------------------------------------------------------------------  
    • |   0 | SELECT STATEMENT        |        |     1 |    34 |     4   (0)| 00:00:01 |  
    • |   1 |  TABLE ACCESS BY INDEX ROWID| EMP_NORMAL |     1 |    34 |     4   (0)| 00:00:01 |  
    • |*  2 |   INDEX RANGE SCAN      | BT_NORMAL  |     1 |   |     3   (0)| 00:00:01 |  
    • ------------------------------------------------------------------------------------------  
    •   
    • Predicate Information (identified by operation id):  
    • ---------------------------------------------------  
    •   
    •    2 - access("EMPNO"=1000)  
    •   
    •   
    • 统计信息  
    • ----------------------------------------------------------  
    •       1  recursive calls  
    •       0  db block gets  
    •       5  consistent gets  
    •       0  physical reads  
    •       0  redo size  
    •     702  bytes sent via SQL*Net to client  
    •     520  bytes received via SQL*Net from client  
    •       2  SQL*Net roundtrips to/from client  
    •       0  sorts (memory)  
    •       0  sorts (disk)  
    •       1  rows processed  
    •   
    • SQL> select * from emp_normal where empno=&empno;  
    • 输入 empno 的值:  128444  
    • 原值    1: select * from emp_normal where empno=&empno  
    • 新值    1: select * from emp_normal where empno=128444  
    •   
    •   
    • 执行计划  
    • ----------------------------------------------------------  
    • Plan hash value: 733975378  
    •   
    • ------------------------------------------------------------------------------------------  
    • | Id  | Operation           | Name   | Rows  | Bytes | Cost (%CPU)| Time     |  
    • ------------------------------------------------------------------------------------------  
    • |   0 | SELECT STATEMENT        |        |     1 |    34 |     4   (0)| 00:00:01 |  
    • |   1 |  TABLE ACCESS BY INDEX ROWID| EMP_NORMAL |     1 |    34 |     4   (0)| 00:00:01 |  
    • |*  2 |   INDEX RANGE SCAN      | BT_NORMAL  |     1 |   |     3   (0)| 00:00:01 |  
    • ------------------------------------------------------------------------------------------  
    •   
    • Predicate Information (identified by operation id):  
    • ---------------------------------------------------  
    •   
    •    2 - access("EMPNO"=128444)  
    •   
    •   
    • 统计信息  
    • ----------------------------------------------------------  
    •       1  recursive calls  
    •       0  db block gets  
    •       5  consistent gets  
    •       0  physical reads  
    •       0  redo size  
    •     704  bytes sent via SQL*Net to client  
    •     520  bytes received via SQL*Net from client  
    •       2  SQL*Net roundtrips to/from client  
    •       0  sorts (memory)  
    •       0  sorts (disk)  
    •       1  rows processed  
    •   
    • SQL> select * from emp_normal where empno=&empno;  
    • 输入 empno 的值:  2398  
    • 原值    1: select * from emp_normal where empno=&empno  
    • 新值    1: select * from emp_normal where empno=2398  
    •   
    •   
    • 执行计划  
    • ----------------------------------------------------------  
    • Plan hash value: 733975378  
    •   
    • ------------------------------------------------------------------------------------------  
    • | Id  | Operation           | Name   | Rows  | Bytes | Cost (%CPU)| Time     |  
    • ------------------------------------------------------------------------------------------  
    • |   0 | SELECT STATEMENT        |        |     1 |    34 |     4   (0)| 00:00:01 |  
    • |   1 |  TABLE ACCESS BY INDEX ROWID| EMP_NORMAL |     1 |    34 |     4   (0)| 00:00:01 |  
    • |*  2 |   INDEX RANGE SCAN      | BT_NORMAL  |     1 |   |     3   (0)| 00:00:01 |  
    • ------------------------------------------------------------------------------------------  
    •   
    • Predicate Information (identified by operation id):  
    • ---------------------------------------------------  
    •   
    •    2 - access("EMPNO"=2398)  
    •   
    •   
    • 统计信息  
    • ----------------------------------------------------------  
    •       1  recursive calls  
    •       0  db block gets  
    •       5  consistent gets  
    •       0  physical reads  
    •       0  redo size  
    •     703  bytes sent via SQL*Net to client  
    •     520  bytes received via SQL*Net from client  
    •       2  SQL*Net roundtrips to/from client  
    •       0  sorts (memory)  
    •       0  sorts (disk)  
    •       1  rows processed  


    总结如下:

    BITMAP EMPNO B-TREE
    Consistent Reads Physical Reads Consistent Reads Physical Reads
    5 0 1000 5 0
    5 0 2398 5 0
    5 0 8545 5 0
    5 0 98008 5 0
    5 0 85342 5 0
    5 0 128444 5 0
    5 0 858 5 0

    对emp_random表进行实验,得出的结果与之类似,这里不再獒述。从这里可以看出,在唯一列上的等值查询,位图索引与btree索引的效率相当。
    下面,我们在针对范围查询来进行测试。

    [sql] view plaincopyprint?


    • SQL> create bitmap index bm_random  on emp_random(empno);  
    •   
    • 索引已创建。  
    •   
    • SQL> analyze table emp_random compute statistics for table for all indexes for all columns;  
    •   
    • 表已分析。  
    •   
    • SQL> select index_name,clustering_factor from user_indexes;  
    •   
    • INDEX_NAME             CLUSTERING_FACTOR  
    • ------------------------------ -----------------  
    • BM_RANDOM                1000000  
    •   
    •   
    • SQL> set autot traceonly  
    • SQL> select * from emp_random where empno between &range1 and &range2;  
    • 输入 range1 的值:  1  
    • 输入 range2 的值:  2300  
    • 原值    1: select * from emp_random where empno between &range1 and &range2  
    • 新值    1: select * from emp_random where empno between 1 and 2300  
    •   
    • 已选择2300行。  
    •   
    •   
    • 执行计划  
    • ----------------------------------------------------------  
    • Plan hash value: 811843605  
    •   
    • -------------------------------------------------------------------------------------------  
    • | Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time     |  
    • -------------------------------------------------------------------------------------------  
    • |   0 | SELECT STATEMENT         |        |  2299 | 85063 |   418   (1)| 00:00:06 |  
    • |   1 |  TABLE ACCESS BY INDEX ROWID | EMP_RANDOM |  2299 | 85063 |   418   (1)| 00:00:06 |  
    • |   2 |   BITMAP CONVERSION TO ROWIDS|        |   |   |        |      |  
    • |*  3 |    BITMAP INDEX RANGE SCAN   | BM_RANDOM  |   |   |        |      |  
    • -------------------------------------------------------------------------------------------  
    •   
    • Predicate Information (identified by operation id):  
    • ---------------------------------------------------  
    •   
    •    3 - access("EMPNO">=1 AND "EMPNO"<=2300)  
    •   
    •   
    • 统计信息  
    • ----------------------------------------------------------  
    •       1  recursive calls  
    •       0  db block gets  
    •        2463  consistent gets  
    •       0  physical reads  
    •       0  redo size  
    •      130225  bytes sent via SQL*Net to client  
    •        2203  bytes received via SQL*Net from client  
    •     155  SQL*Net roundtrips to/from client  
    •       0  sorts (memory)  
    •       0  sorts (disk)  
    •        2300  rows processed  
    •   
    • SQL> select * from emp_random where empno between &range1 and &range2;  
    • 输入 range1 的值:  8  
    • 输入 range2 的值:  1980  
    • 原值    1: select * from emp_random where empno between &range1 and &range2  
    • 新值    1: select * from emp_random where empno between 8 and 1980  
    •   
    • 已选择1973行。  
    •   
    •   
    • 执行计划  
    • ----------------------------------------------------------  
    • Plan hash value: 811843605  
    •   
    • -------------------------------------------------------------------------------------------  
    • | Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time     |  
    • -------------------------------------------------------------------------------------------  
    • |   0 | SELECT STATEMENT         |        |  1972 | 72964 |   366   (0)| 00:00:05 |  
    • |   1 |  TABLE ACCESS BY INDEX ROWID | EMP_RANDOM |  1972 | 72964 |   366   (0)| 00:00:05 |  
    • |   2 |   BITMAP CONVERSION TO ROWIDS|        |   |   |        |      |  
    • |*  3 |    BITMAP INDEX RANGE SCAN   | BM_RANDOM  |   |   |        |      |  
    • -------------------------------------------------------------------------------------------  
    •   
    • Predicate Information (identified by operation id):  
    • ---------------------------------------------------  
    •   
    •    3 - access("EMPNO">=8 AND "EMPNO"<=1980)  
    •   
    •   
    • 统计信息  
    • ----------------------------------------------------------  
    •       1  recursive calls  
    •       0  db block gets  
    •        2114  consistent gets  
    •       0  physical reads  
    •       0  redo size  
    •      111758  bytes sent via SQL*Net to client  
    •        1961  bytes received via SQL*Net from client  
    •     133  SQL*Net roundtrips to/from client  
    •       0  sorts (memory)  
    •       0  sorts (disk)  
    •        1973  rows processed  
    •   
    • SQL> select * from emp_random where empno between &range1 and &range2;  
    • 输入 range1 的值:  28888  
    • 输入 range2 的值:  31850  
    • 原值    1: select * from emp_random where empno between &range1 and &range2  
    • 新值    1: select * from emp_random where empno between 28888 and 31850  
    •   
    • 已选择2963行。  
    •   
    •   
    • 执行计划  
    • ----------------------------------------------------------  
    • Plan hash value: 811843605  
    •   
    • -------------------------------------------------------------------------------------------  
    • | Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time     |  
    • -------------------------------------------------------------------------------------------  
    • |   0 | SELECT STATEMENT         |        |  2962 |   107K|   513   (0)| 00:00:07 |  
    • |   1 |  TABLE ACCESS BY INDEX ROWID | EMP_RANDOM |  2962 |   107K|   513   (0)| 00:00:07 |  
    • |   2 |   BITMAP CONVERSION TO ROWIDS|        |   |   |        |      |  
    • |*  3 |    BITMAP INDEX RANGE SCAN   | BM_RANDOM  |   |   |        |      |  
    • -------------------------------------------------------------------------------------------  
    •   
    • Predicate Information (identified by operation id):  
    • ---------------------------------------------------  
    •   
    •    3 - access("EMPNO">=28888 AND "EMPNO"<=31850)  
    •   
    •   
    • 统计信息  
    • ----------------------------------------------------------  
    •       1  recursive calls  
    •       0  db block gets  
    •        3172  consistent gets  
    •       0  physical reads  
    •       0  redo size  
    •      170625  bytes sent via SQL*Net to client  
    •        2687  bytes received via SQL*Net from client  
    •     199  SQL*Net roundtrips to/from client  
    •       0  sorts (memory)  
    •       0  sorts (disk)  
    •        2963  rows processed  
    •   
    • SQL> drop index bm_random;  
    •   
    • 索引已删除。  
    •   
    • SQL> create index bt_random on emp_random(empno);  
    •   
    • 索引已创建。  
    •   
    • SQL> analyze table emp_random compute statistics for table for all indexes for all columns;  
    •   
    • 表已分析。  
    •   
    • SQL> set autot off  
    • SQL> select index_name,clustering_factor from user_indexes;  
    •   
    • INDEX_NAME             CLUSTERING_FACTOR  
    • ------------------------------ -----------------  
    • BT_RANDOM                 999834  
    • SQL> set autot traceonly  
    • SQL> select * from emp_random where empno between &range1 and &range2;  
    • 输入 range1 的值:  1  
    • 输入 range2 的值:  2300  
    • 原值    1: select * from emp_random where empno between &range1 and &range2  
    • 新值    1: select * from emp_random where empno between 1 and 2300  
    •   
    • 已选择2300行。  
    •   
    •   
    • 执行计划  
    • ----------------------------------------------------------  
    • Plan hash value: 731629521  
    •   
    • --------------------------------------------------------------------------------  
    • | Id  | Operation     | Name       | Rows  | Bytes | Cost (%CPU)| Time     |  
    • --------------------------------------------------------------------------------  
    • |   0 | SELECT STATEMENT  |        |  2299 | 85063 |  1735   (1)| 00:00:21 |  
    • |*  1 |  TABLE ACCESS FULL| EMP_RANDOM |  2299 | 85063 |  1735   (1)| 00:00:21 |  
    • --------------------------------------------------------------------------------  
    •   
    • Predicate Information (identified by operation id):  
    • ---------------------------------------------------  
    •   
    •    1 - filter("EMPNO"<=2300 AND "EMPNO">=1)  
    •   
    •   
    • 统计信息  
    • ----------------------------------------------------------  
    •       1  recursive calls  
    •       0  db block gets  
    •        6410  consistent gets  
    •       0  physical reads  
    •       0  redo size  
    •      121081  bytes sent via SQL*Net to client  
    •        2203  bytes received via SQL*Net from client  
    •     155  SQL*Net roundtrips to/from client  
    •       0  sorts (memory)  
    •       0  sorts (disk)  
    •        2300  rows processed  
    •   
    • SQL> select * from emp_random where empno between &range1 and &range2;  
    • 输入 range1 的值:  8  
    • 输入 range2 的值:  1980  
    • 原值    1: select * from emp_random where empno between &range1 and &range2  
    • 新值    1: select * from emp_random where empno between 8 and 1980  
    •   
    • 已选择1973行。  
    •   
    •   
    • 执行计划  
    • ----------------------------------------------------------  
    • Plan hash value: 731629521  
    •   
    • --------------------------------------------------------------------------------  
    • | Id  | Operation     | Name       | Rows  | Bytes | Cost (%CPU)| Time     |  
    • --------------------------------------------------------------------------------  
    • |   0 | SELECT STATEMENT  |        |  1972 | 72964 |  1735   (1)| 00:00:21 |  
    • |*  1 |  TABLE ACCESS FULL| EMP_RANDOM |  1972 | 72964 |  1735   (1)| 00:00:21 |  
    • --------------------------------------------------------------------------------  
    •   
    • Predicate Information (identified by operation id):  
    • ---------------------------------------------------  
    •   
    •    1 - filter("EMPNO"<=1980 AND "EMPNO">=8)  
    •   
    •   
    • 统计信息  
    • ----------------------------------------------------------  
    •       1  recursive calls  
    •       0  db block gets  
    •        6388  consistent gets  
    •       0  physical reads  
    •       0  redo size  
    •      103922  bytes sent via SQL*Net to client  
    •        1961  bytes received via SQL*Net from client  
    •     133  SQL*Net roundtrips to/from client  
    •       0  sorts (memory)  
    •       0  sorts (disk)  
    •        1973  rows processed  



    归纳如下,

    BITMAP EMPNO (Range) B-TREE
    Consistent Reads Physical Reads Consistent Reads Physical Reads
    2463 0 1-2300 6410 0
    2114 0 8-1980 6388 0
    2572 0 1850-4250 6418 0
    3172 0 28888-31850 6456 0
    2762 0 82900-85478 6431 0
    7254 0 984888-1000000 7254 0

    从这里可以看出,位图索引要优于btree索引,这是因为btree索引的cluster  factor 较大,从而优化器选择了全表扫描。即便在emp_normal 表下,即clustering factor较小时,位图索引btree索引相当的。因此在distinct cardinality 较大的情况下,范围扫描的效率位图索引也是不逊色与btree索引。
    总结如下:
    位图索引的查询性能经常是优于btree索引的,即便在distinct cardinality较大的情况下
    位图索引不适合与dml频繁的环境
    位图索引适用于DSS系统
    位图索引可以进行逻辑运算,多个索引和同时在查询语句中发挥作用,这是一个非常重要的地方

  • 相关阅读:
    Linux下C程序的反汇编【转】
    数据在内存中的存储方式( Big Endian和Little Endian的区别 )(x86系列则采用little endian方式存储数据)【转】
    linux arm的存储分布那些事之一【转】
    linux arm mmu基础【转】
    linux 进程内存解析【转】
    如何更方便的查看Linux内核代码的更新记录【转】
    设备树解析【转】
    分析内核源码,设备树【转】
     Meltdown论文翻译【转】
    device tree --- #address-cells and #size-cells property【转】
  • 原文地址:https://www.cnblogs.com/rattersnake/p/3496974.html
Copyright © 2011-2022 走看看