详解oracle bitmap位图索引

原文地址:http://blog.csdn.net/yidian815/article/details/16891021

位图索引是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 plain  copy
  1. CREATE or replace FUNCTION ind_spc_test(rn NUMBER) RETURN NUMBER  
  2.   AS  
  3.       v_j     NUMBER;  
  4.       v_dis   NUMBER;  
  5.       v_bm_sp NUMBER;  
  6.       v_bt_sp NUMBER;  
  7.     BEGIN  
  8.       FOR i IN 1 .. 10LOOP  
  9.         EXECUTE immediate 'truncate table t_easy1';  
  10.         EXECUTE immediate 'truncate table t_easy2';  
  11.         SELECT floor(rn/(11-i)) INTO v_j FROM dual;  
  12.         FOR j IN 1 .. rn LOOP  
  13.           INSERT INTO t_easy1 VALUES (mod(j,v_j));  
  14.           INSERT INTO t_easy2 VALUES (mod(j,v_j));  
  15.         END LOOP;  
  16.         commit;  
  17.         select count(distinct id) into v_j from t_easy1;  
  18.         EXECUTE immediate 'analyze index i_easy1 COMPUTE STATISTICS';  
  19.         SELECT lEAF_BLOCKS INTO v_bt_sp FROM user_indexes where index_name='I_EASY1';  
  20.         EXECUTE immediate 'analyze index i_easy2 COMPUTE STATISTICS';  
  21.         SELECT LEAF_BLOCKS INTO v_bm_sp FROM user_indexes where index_name='I_EASY2';  
  22.         INSERT INTO bitmap_ind_space VALUES (v_j,v_bm_sp,v_bt_sp,rn );  
  23.         COMMIT;  
  24.       END LOOP;  
  25.       RETURN 0;  
  26.     END;  

[sql]  view plain  copy
  1. SQL> select * from bitmap_ind_space order by 1;  
  2.   
  3. DISTINCT_VAL BITMAP_IND_BLKS BTREE_IND_BLKS    ROW_NUM  
  4. ------------ --------------- -------------- ----------  
  5.        10000         139        300 100000  
  6.        11111          79        335 100000  
  7.        12500          89        285 100000  
  8.        14285         103        220 100000  
  9.        16666         120        257 100000  
  10.        20000         146        310 100000  
  11.        25000         183        293 100000  
  12.        33333         246        262 100000  
  13.        50000         371        296 100000  
  14.       100000         408        200 100000  

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


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

位图索引的查询性能如何?

下面我们看一下位图索引的查询性能如何。
在很多资料中,都可以看到这样的论述:位图索引适合于 low distict cardinality的列。实际上,对于high distinct cardinality 的列,位图索引的查询性能也是非常不错的。下面我们来验证这个结论。
首先我们创建两张表:emp_normal和emp_random.
[sql]  view plain  copy
  1. SQL> create table emp_normal(empno number(10), ename varchar2(30), sal number(10));  
  2.   
  3. 表已创建。  
  4.   
  5. Begin  
  6. For i in 1..1000000  
  7. Loop  
  8.    Insert into emp_normal   
  9.    values(i, dbms_random.string('U',30), dbms_random.value(1000,7000));  
  10.    If mod(i, 10000) = 0 then  
  11.    Commit;  
  12.   End if;  
  13. End loop;  
  14.  10  End;  
  15.  11  /  
  16.   
  17. PL/SQL 过程已成功完成。  
  18.   
  19. SQL> create table emp_random as select /* +append */ * from emp_normal order by dbms_random.random;  
emp_random由于其记录是随机分布的,因此该表上索引的CLUSTERING_FACTOR要高一些。
我们首先看一下emp_normal表等值查询情况下,索引的效率如何:
[sql]  view plain  copy
  1. SQL> create bitmap index bm_normal on emp_normal(empno);  
  2.   
  3. 索引已创建。  
  4.   
  5.   
  6. SQL> analyze table emp_normal compute statistics for table for all indexes for all indexed columns;  
  7.   
  8. 表已分析。  
  9.   
  10. SQL> select index_name,clustering_factor from user_indexes;  
  11.   
  12. INDEX_NAME             CLUSTERING_FACTOR  
  13. ------------------------------ -----------------  
  14. BM_NORMAL                1000000  
  15.   
  16. SQL> set autot traceonly  
  17. SQL> select * from emp_normal where empno=&empno;  
  18. 输入 empno 的值:  1000  
  19. 原值    1: select * from emp_normal where empno=&empno  
  20. 新值    1: select * from emp_normal where empno=1000  
  21.   
  22.   
  23. 执行计划  
  24. ----------------------------------------------------------  
  25. Plan hash value: 1526426521  
  26.   
  27. -------------------------------------------------------------------------------------------  
  28. | Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time     |  
  29. -------------------------------------------------------------------------------------------  
  30. |   0 | SELECT STATEMENT         |        | 1 |    34 | 3   (0)| 00:00:01 |  
  31. |   1 |  TABLE ACCESS BY INDEX ROWID | EMP_NORMAL | 1 |    34 | 3   (0)| 00:00:01 |  
  32. |   2 |   BITMAP CONVERSION TO ROWIDS|        |   |   |        |      |  
  33. |*  3 |    BITMAP INDEX SINGLE VALUE | BM_NORMAL  |   |   |        |      |  
  34. -------------------------------------------------------------------------------------------  
  35.   
  36. Predicate Information (identified by operation id):  
  37. ---------------------------------------------------  
  38.   
  39.    3 - access("EMPNO"=1000)  
  40.   
  41.   
  42. 统计信息  
  43. ----------------------------------------------------------  
  44.       1  recursive calls  
  45.       0  db block gets  
  46.       5  consistent gets  
  47.       0  physical reads  
  48.       0  redo size  
  49.     702  bytes sent via SQL*Net to client  
  50.     520  bytes received via SQL*Net from client  
  51.       2  SQL*Net roundtrips to/from client  
  52.       0  sorts (memory)  
  53.       0  sorts (disk)  
  54.       1  rows processed  
  55.   
  56. SQL> select * from emp_normal where empno=&empno;  
  57. 输入 empno 的值:  2398  
  58. 原值    1: select * from emp_normal where empno=&empno  
  59. 新值    1: select * from emp_normal where empno=2398  
  60.   
  61.   
  62. 执行计划  
  63. ----------------------------------------------------------  
  64. Plan hash value: 1526426521  
  65.   
  66. -------------------------------------------------------------------------------------------  
  67. | Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time     |  
  68. -------------------------------------------------------------------------------------------  
  69. |   0 | SELECT STATEMENT         |        | 1 |    34 | 3   (0)| 00:00:01 |  
  70. |   1 |  TABLE ACCESS BY INDEX ROWID | EMP_NORMAL | 1 |    34 | 3   (0)| 00:00:01 |  
  71. |   2 |   BITMAP CONVERSION TO ROWIDS|        |   |   |        |      |  
  72. |*  3 |    BITMAP INDEX SINGLE VALUE | BM_NORMAL  |   |   |        |      |  
  73. -------------------------------------------------------------------------------------------  
  74.   
  75. Predicate Information (identified by operation id):  
  76. ---------------------------------------------------  
  77.   
  78.    3 - access("EMPNO"=2398)  
  79.   
  80.   
  81. 统计信息  
  82. ----------------------------------------------------------  
  83.       1  recursive calls  
  84.       0  db block gets  
  85.       5  consistent gets  
  86.       0  physical reads  
  87.       0  redo size  
  88.     703  bytes sent via SQL*Net to client  
  89.     520  bytes received via SQL*Net from client  
  90.       2  SQL*Net roundtrips to/from client  
  91.       0  sorts (memory)  
  92.       0  sorts (disk)  
  93.       1  rows processed  
  94.   
  95. SQL> select * from emp_normal where empno=&empno;  
  96. 输入 empno 的值:  8545  
  97. 原值    1: select * from emp_normal where empno=&empno  
  98. 新值    1: select * from emp_normal where empno=8545  
  99.   
  100.   
  101. 执行计划  
  102. ----------------------------------------------------------  
  103. Plan hash value: 1526426521  
  104.   
  105. -------------------------------------------------------------------------------------------  
  106. | Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time     |  
  107. -------------------------------------------------------------------------------------------  
  108. |   0 | SELECT STATEMENT         |        | 1 |    34 | 3   (0)| 00:00:01 |  
  109. |   1 |  TABLE ACCESS BY INDEX ROWID | EMP_NORMAL | 1 |    34 | 3   (0)| 00:00:01 |  
  110. |   2 |   BITMAP CONVERSION TO ROWIDS|        |   |   |        |      |  
  111. |*  3 |    BITMAP INDEX SINGLE VALUE | BM_NORMAL  |   |   |        |      |  
  112. -------------------------------------------------------------------------------------------  
  113.   
  114. Predicate Information (identified by operation id):  
  115. ---------------------------------------------------  
  116.   
  117.    3 - access("EMPNO"=8545)  
  118.   
  119.   
  120. 统计信息  
  121. ----------------------------------------------------------  
  122.       1  recursive calls  
  123.       0  db block gets  
  124.       5  consistent gets  
  125.       0  physical reads  
  126.       0  redo size  
  127.     703  bytes sent via SQL*Net to client  
  128.     520  bytes received via SQL*Net from client  
  129.       2  SQL*Net roundtrips to/from client  
  130.       0  sorts (memory)  
  131.       0  sorts (disk)  
  132.       1  rows processed  
  133.   
  134. SQL> select * from emp_normal where empno=&empno;  
  135. 输入 empno 的值:  128444  
  136. 原值    1: select * from emp_normal where empno=&empno  
  137. 新值    1: select * from emp_normal where empno=128444  
  138.   
  139.   
  140. 执行计划  
  141. ----------------------------------------------------------  
  142. Plan hash value: 1526426521  
  143.   
  144. -------------------------------------------------------------------------------------------  
  145. | Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time     |  
  146. -------------------------------------------------------------------------------------------  
  147. |   0 | SELECT STATEMENT         |        | 1 |    34 | 3   (0)| 00:00:01 |  
  148. |   1 |  TABLE ACCESS BY INDEX ROWID | EMP_NORMAL | 1 |    34 | 3   (0)| 00:00:01 |  
  149. |   2 |   BITMAP CONVERSION TO ROWIDS|        |   |   |        |      |  
  150. |*  3 |    BITMAP INDEX SINGLE VALUE | BM_NORMAL  |   |   |        |      |  
  151. -------------------------------------------------------------------------------------------  
  152.   
  153. Predicate Information (identified by operation id):  
  154. ---------------------------------------------------  
  155.   
  156.    3 - access("EMPNO"=128444)  
  157.   
  158.   
  159. 统计信息  
  160. ----------------------------------------------------------  
  161.       1  recursive calls  
  162.       0  db block gets  
  163.       5  consistent gets  
  164.       0  physical reads  
  165.       0  redo size  
  166.     704  bytes sent via SQL*Net to client  
  167.     520  bytes received via SQL*Net from client  
  168.       2  SQL*Net roundtrips to/from client  
  169.       0  sorts (memory)  
  170.       0  sorts (disk)  
  171.       1  rows processed  
  172.   
  173. SQL> drop index bm_normal;  
  174.   
  175. 索引已删除。  
  176.   
  177. SQL> create index bt_normal on emp_normal(empno);  
  178.   
  179. 索引已创建。  
  180.   
  181. SQL> analyze table emp_normal compute statistics for table for all indexes for all indexed columns;  
  182.   
  183. 表已分析。  
  184.   
  185. SQL> select index_name,clustering_factor from user_indexes;  
  186.   
  187. INDEX_NAME             CLUSTERING_FACTOR  
  188. ------------------------------ -----------------  
  189. BT_NORMAL                   6210  
  190. SYS_IL0000076897C00002$$  
  191. PK_EMP                         1  
  192. PK_DEPT                        1  
  193.   
  194. SQL> set autot traceonly  
  195. SQL> select * from emp_normal where empno=&empno;  
  196. 输入 empno 的值:  1000  
  197. 原值    1: select * from emp_normal where empno=&empno  
  198. 新值    1: select * from emp_normal where empno=1000  
  199.   
  200.   
  201. 执行计划  
  202. ----------------------------------------------------------  
  203. Plan hash value: 733975378  
  204.   
  205. ------------------------------------------------------------------------------------------  
  206. | Id  | Operation           | Name   | Rows  | Bytes | Cost (%CPU)| Time     |  
  207. ------------------------------------------------------------------------------------------  
  208. |   0 | SELECT STATEMENT        |        |     1 |    34 |     4   (0)| 00:00:01 |  
  209. |   1 |  TABLE ACCESS BY INDEX ROWID| EMP_NORMAL |     1 |    34 |     4   (0)| 00:00:01 |  
  210. |*  2 |   INDEX RANGE SCAN      | BT_NORMAL  |     1 |   |     3   (0)| 00:00:01 |  
  211. ------------------------------------------------------------------------------------------  
  212.   
  213. Predicate Information (identified by operation id):  
  214. ---------------------------------------------------  
  215.   
  216.    2 - access("EMPNO"=1000)  
  217.   
  218.   
  219. 统计信息  
  220. ----------------------------------------------------------  
  221.       1  recursive calls  
  222.       0  db block gets  
  223.       5  consistent gets  
  224.       0  physical reads  
  225.       0  redo size  
  226.     702  bytes sent via SQL*Net to client  
  227.     520  bytes received via SQL*Net from client  
  228.       2  SQL*Net roundtrips to/from client  
  229.       0  sorts (memory)  
  230.       0  sorts (disk)  
  231.       1  rows processed  
  232.   
  233. SQL> select * from emp_normal where empno=&empno;  
  234. 输入 empno 的值:  128444  
  235. 原值    1: select * from emp_normal where empno=&empno  
  236. 新值    1: select * from emp_normal where empno=128444  
  237.   
  238.   
  239. 执行计划  
  240. ----------------------------------------------------------  
  241. Plan hash value: 733975378  
  242.   
  243. ------------------------------------------------------------------------------------------  
  244. | Id  | Operation           | Name   | Rows  | Bytes | Cost (%CPU)| Time     |  
  245. ------------------------------------------------------------------------------------------  
  246. |   0 | SELECT STATEMENT        |        |     1 |    34 |     4   (0)| 00:00:01 |  
  247. |   1 |  TABLE ACCESS BY INDEX ROWID| EMP_NORMAL |     1 |    34 |     4   (0)| 00:00:01 |  
  248. |*  2 |   INDEX RANGE SCAN      | BT_NORMAL  |     1 |   |     3   (0)| 00:00:01 |  
  249. ------------------------------------------------------------------------------------------  
  250.   
  251. Predicate Information (identified by operation id):  
  252. ---------------------------------------------------  
  253.   
  254.    2 - access("EMPNO"=128444)  
  255.   
  256.   
  257. 统计信息  
  258. ----------------------------------------------------------  
  259.       1  recursive calls  
  260.       0  db block gets  
  261.       5  consistent gets  
  262.       0  physical reads  
  263.       0  redo size  
  264.     704  bytes sent via SQL*Net to client  
  265.     520  bytes received via SQL*Net from client  
  266.       2  SQL*Net roundtrips to/from client  
  267.       0  sorts (memory)  
  268.       0  sorts (disk)  
  269.       1  rows processed  
  270.   
  271. SQL> select * from emp_normal where empno=&empno;  
  272. 输入 empno 的值:  2398  
  273. 原值    1: select * from emp_normal where empno=&empno  
  274. 新值    1: select * from emp_normal where empno=2398  
  275.   
  276.   
  277. 执行计划  
  278. ----------------------------------------------------------  
  279. Plan hash value: 733975378  
  280.   
  281. ------------------------------------------------------------------------------------------  
  282. | Id  | Operation           | Name   | Rows  | Bytes | Cost (%CPU)| Time     |  
  283. ------------------------------------------------------------------------------------------  
  284. |   0 | SELECT STATEMENT        |        |     1 |    34 |     4   (0)| 00:00:01 |  
  285. |   1 |  TABLE ACCESS BY INDEX ROWID| EMP_NORMAL |     1 |    34 |     4   (0)| 00:00:01 |  
  286. |*  2 |   INDEX RANGE SCAN      | BT_NORMAL  |     1 |   |     3   (0)| 00:00:01 |  
  287. ------------------------------------------------------------------------------------------  
  288.   
  289. Predicate Information (identified by operation id):  
  290. ---------------------------------------------------  
  291.   
  292.    2 - access("EMPNO"=2398)  
  293.   
  294.   
  295. 统计信息  
  296. ----------------------------------------------------------  
  297.       1  recursive calls  
  298.       0  db block gets  
  299.       5  consistent gets  
  300.       0  physical reads  
  301.       0  redo size  
  302.     703  bytes sent via SQL*Net to client  
  303.     520  bytes received via SQL*Net from client  
  304.       2  SQL*Net roundtrips to/from client  
  305.       0  sorts (memory)  
  306.       0  sorts (disk)  
  307.       1  rows processed  
总结如下:
BITMAPEMPNOB-TREE
Consistent ReadsPhysical ReadsConsistent ReadsPhysical Reads
50100050
50239850
50854550
509800850
508534250
5012844450
5085850

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

下面,我们在针对范围查询来进行测试。

[sql]  view plain  copy
  1. SQL> create bitmap index bm_random  on emp_random(empno);  
  2.   
  3. 索引已创建。  
  4.   
  5. SQL> analyze table emp_random compute statistics for table for all indexes for all columns;  
  6.   
  7. 表已分析。  
  8.   
  9. SQL> select index_name,clustering_factor from user_indexes;  
  10.   
  11. INDEX_NAME             CLUSTERING_FACTOR  
  12. ------------------------------ -----------------  
  13. BM_RANDOM                1000000  
  14.   
  15.   
  16. SQL> set autot traceonly  
  17. SQL> select * from emp_random where empno between &range1 and &range2;  
  18. 输入 range1 的值:  1  
  19. 输入 range2 的值:  2300  
  20. 原值    1: select * from emp_random where empno between &range1 and &range2  
  21. 新值    1: select * from emp_random where empno between 1 and 2300  
  22.   
  23. 已选择2300行。  
  24.   
  25.   
  26. 执行计划  
  27. ----------------------------------------------------------  
  28. Plan hash value: 811843605  
  29.   
  30. -------------------------------------------------------------------------------------------  
  31. | Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time     |  
  32. -------------------------------------------------------------------------------------------  
  33. |   0 | SELECT STATEMENT         |        |  2299 | 85063 |   418   (1)| 00:00:06 |  
  34. |   1 |  TABLE ACCESS BY INDEX ROWID | EMP_RANDOM |  2299 | 85063 |   418   (1)| 00:00:06 |  
  35. |   2 |   BITMAP CONVERSION TO ROWIDS|        |   |   |        |      |  
  36. |*  3 |    BITMAP INDEX RANGE SCAN   | BM_RANDOM  |   |   |        |      |  
  37. -------------------------------------------------------------------------------------------  
  38.   
  39. Predicate Information (identified by operation id):  
  40. ---------------------------------------------------  
  41.   
  42.    3 - access("EMPNO">=1 AND "EMPNO"<=2300)  
  43.   
  44.   
  45. 统计信息  
  46. ----------------------------------------------------------  
  47.       1  recursive calls  
  48.       0  db block gets  
  49.        2463  consistent gets  
  50.       0  physical reads  
  51.       0  redo size  
  52.      130225  bytes sent via SQL*Net to client  
  53.        2203  bytes received via SQL*Net from client  
  54.     155  SQL*Net roundtrips to/from client  
  55.       0  sorts (memory)  
  56.       0  sorts (disk)  
  57.        2300  rows processed  
  58.   
  59. SQL> select * from emp_random where empno between &range1 and &range2;  
  60. 输入 range1 的值:  8  
  61. 输入 range2 的值:  1980  
  62. 原值    1: select * from emp_random where empno between &range1 and &range2  
  63. 新值    1: select * from emp_random where empno between 8 and 1980  
  64.   
  65. 已选择1973行。  
  66.   
  67.   
  68. 执行计划  
  69. ----------------------------------------------------------  
  70. Plan hash value: 811843605  
  71.   
  72. -------------------------------------------------------------------------------------------  
  73. | Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time     |  
  74. -------------------------------------------------------------------------------------------  
  75. |   0 | SELECT STATEMENT         |        |  1972 | 72964 |   366   (0)| 00:00:05 |  
  76. |   1 |  TABLE ACCESS BY INDEX ROWID | EMP_RANDOM |  1972 | 72964 |   366   (0)| 00:00:05 |  
  77. |   2 |   BITMAP CONVERSION TO ROWIDS|        |   |   |        |      |  
  78. |*  3 |    BITMAP INDEX RANGE SCAN   | BM_RANDOM  |   |   |        |      |  
  79. -------------------------------------------------------------------------------------------  
  80.   
  81. Predicate Information (identified by operation id):  
  82. ---------------------------------------------------  
  83.   
  84.    3 - access("EMPNO">=8 AND "EMPNO"<=1980)  
  85.   
  86.   
  87. 统计信息  
  88. ----------------------------------------------------------  
  89.       1  recursive calls  
  90.       0  db block gets  
  91.        2114  consistent gets  
  92.       0  physical reads  
  93.       0  redo size  
  94.      111758  bytes sent via SQL*Net to client  
  95.        1961  bytes received via SQL*Net from client  
  96.     133  SQL*Net roundtrips to/from client  
  97.       0  sorts (memory)  
  98.       0  sorts (disk)  
  99.        1973  rows processed  
  100.   
  101. SQL> select * from emp_random where empno between &range1 and &range2;  
  102. 输入 range1 的值:  28888  
  103. 输入 range2 的值:  31850  
  104. 原值    1: select * from emp_random where empno between &range1 and &range2  
  105. 新值    1: select * from emp_random where empno between 28888 and 31850  
  106.   
  107. 已选择2963行。  
  108.   
  109.   
  110. 执行计划  
  111. ----------------------------------------------------------  
  112. Plan hash value: 811843605  
  113.   
  114. -------------------------------------------------------------------------------------------  
  115. | Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time     |  
  116. -------------------------------------------------------------------------------------------  
  117. |   0 | SELECT STATEMENT         |        |  2962 |   107K|   513   (0)| 00:00:07 |  
  118. |   1 |  TABLE ACCESS BY INDEX ROWID | EMP_RANDOM |  2962 |   107K|   513   (0)| 00:00:07 |  
  119. |   2 |   BITMAP CONVERSION TO ROWIDS|        |   |   |        |      |  
  120. |*  3 |    BITMAP INDEX RANGE SCAN   | BM_RANDOM  |   |   |        |      |  
  121. -------------------------------------------------------------------------------------------  
  122.   
  123. Predicate Information (identified by operation id):  
  124. ---------------------------------------------------  
  125.   
  126.    3 - access("EMPNO">=28888 AND "EMPNO"<=31850)  
  127.   
  128.   
  129. 统计信息  
  130. ----------------------------------------------------------  
  131.       1  recursive calls  
  132.       0  db block gets  
  133.        3172  consistent gets  
  134.       0  physical reads  
  135.       0  redo size  
  136.      170625  bytes sent via SQL*Net to client  
  137.        2687  bytes received via SQL*Net from client  
  138.     199  SQL*Net roundtrips to/from client  
  139.       0  sorts (memory)  
  140.       0  sorts (disk)  
  141.        2963  rows processed  
  142.   
  143. SQL> drop index bm_random;  
  144.   
  145. 索引已删除。  
  146.   
  147. SQL> create index bt_random on emp_random(empno);  
  148.   
  149. 索引已创建。  
  150.   
  151. SQL> analyze table emp_random compute statistics for table for all indexes for all columns;  
  152.   
  153. 表已分析。  
  154.   
  155. SQL> set autot off  
  156. SQL> select index_name,clustering_factor from user_indexes;  
  157.   
  158. INDEX_NAME             CLUSTERING_FACTOR  
  159. ------------------------------ -----------------  
  160. BT_RANDOM                 999834  
  161. SQL> set autot traceonly  
  162. SQL> select * from emp_random where empno between &range1 and &range2;  
  163. 输入 range1 的值:  1  
  164. 输入 range2 的值:  2300  
  165. 原值    1: select * from emp_random where empno between &range1 and &range2  
  166. 新值    1: select * from emp_random where empno between 1 and 2300  
  167.   
  168. 已选择2300行。  
  169.   
  170.   
  171. 执行计划  
  172. ----------------------------------------------------------  
  173. Plan hash value: 731629521  
  174.   
  175. --------------------------------------------------------------------------------  
  176. | Id  | Operation     | Name       | Rows  | Bytes | Cost (%CPU)| Time     |  
  177. --------------------------------------------------------------------------------  
  178. |   0 | SELECT STATEMENT  |        |  2299 | 85063 |  1735   (1)| 00:00:21 |  
  179. |*  1 |  TABLE ACCESS FULL| EMP_RANDOM |  2299 | 85063 |  1735   (1)| 00:00:21 |  
  180. --------------------------------------------------------------------------------  
  181.   
  182. Predicate Information (identified by operation id):  
  183. ---------------------------------------------------  
  184.   
  185.    1 - filter("EMPNO"<=2300 AND "EMPNO">=1)  
  186.   
  187.   
  188. 统计信息  
  189. ----------------------------------------------------------  
  190.       1  recursive calls  
  191.       0  db block gets  
  192.        6410  consistent gets  
  193.       0  physical reads  
  194.       0  redo size  
  195.      121081  bytes sent via SQL*Net to client  
  196.        2203  bytes received via SQL*Net from client  
  197.     155  SQL*Net roundtrips to/from client  
  198.       0  sorts (memory)  
  199.       0  sorts (disk)  
  200.        2300  rows processed  
  201.   
  202. SQL> select * from emp_random where empno between &range1 and &range2;  
  203. 输入 range1 的值:  8  
  204. 输入 range2 的值:  1980  
  205. 原值    1: select * from emp_random where empno between &range1 and &range2  
  206. 新值    1: select * from emp_random where empno between 8 and 1980  
  207.   
  208. 已选择1973行。  
  209.   
  210.   
  211. 执行计划  
  212. ----------------------------------------------------------  
  213. Plan hash value: 731629521  
  214.   
  215. --------------------------------------------------------------------------------  
  216. | Id  | Operation     | Name       | Rows  | Bytes | Cost (%CPU)| Time     |  
  217. --------------------------------------------------------------------------------  
  218. |   0 | SELECT STATEMENT  |        |  1972 | 72964 |  1735   (1)| 00:00:21 |  
  219. |*  1 |  TABLE ACCESS FULL| EMP_RANDOM |  1972 | 72964 |  1735   (1)| 00:00:21 |  
  220. --------------------------------------------------------------------------------  
  221.   
  222. Predicate Information (identified by operation id):  
  223. ---------------------------------------------------  
  224.   
  225.    1 - filter("EMPNO"<=1980 AND "EMPNO">=8)  
  226.   
  227.   
  228. 统计信息  
  229. ----------------------------------------------------------  
  230.       1  recursive calls  
  231.       0  db block gets  
  232.        6388  consistent gets  
  233.       0  physical reads  
  234.       0  redo size  
  235.      103922  bytes sent via SQL*Net to client  
  236.        1961  bytes received via SQL*Net from client  
  237.     133  SQL*Net roundtrips to/from client  
  238.       0  sorts (memory)  
  239.       0  sorts (disk)  
  240.        1973  rows processed  

归纳如下,
BITMAPEMPNO (Range)B-TREE
Consistent ReadsPhysical ReadsConsistent ReadsPhysical Reads
246301-230064100
211408-198063880
257201850-425064180
3172028888-3185064560
2762082900-8547864310
72540984888-100000072540

从这里可以看出,位图索引要优于btree索引,这是因为btree索引的cluster  factor 较大,从而优化器选择了全表扫描。即便在emp_normal 表下,即clustering factor较小时,位图索引btree索引相当的。因此在distinct cardinality 较大的情况下,范围扫描的效率位图索引也是不逊色与btree索引。

总结如下:

位图索引的查询性能经常是优于btree索引的,即便在distinct cardinality较大的情况下

位图索引不适合与dml频繁的环境

位图索引适用于DSS系统

位图索引可以进行逻辑运算,多个索引和同时在查询语句中发挥作用,这是一个非常重要的地方


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值