bitmap index

bitmap index 适用于 dss(决策支持系统) 和Data warehouse,ORACLE 建议的是不要在繁重的OLTP中使用 bitmap index ,我
个人建议:千万别在OLTP中使用bitmap index,否则你死定了。
请看一下测试:
SQL> create table test as select * from dba_objects;
表已创建。
SQL> update test set status='INVALID' where owner='SCOTT';
已更新13行。
SQL> commit;
提交完成。
SQL> exec dbms_stats.gather_table_stats('ROBINSON','TEST');
PL/SQL 过程已成功完成。
SQL> create bitmap index i_b_stats on test(status);
索引已创建。
SQL> select count(*) from test where status='INVALID';
  COUNT(*)
----------
        14
执行计划
----------------------------------------------------------
Plan hash value: 148891143
-----------------------------------------------------------------------------------------
| Id  | Operation                   | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |           |     1 |     7 |     1   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE             |           |     1 |     7 |            |          |
|   2 |   BITMAP CONVERSION COUNT   |           | 24981 |   170K|     1   (0)| 00:00:01 |
|*  3 |    BITMAP INDEX SINGLE VALUE| I_B_STATS |       |       |            |          |
-----------------------------------------------------------------------------------------
SQL> drop index i_b_stats ;
索引已删除。
SQL> exec dbms_stats.gather_table_stats('ROBINSON','TEST',method_opt=>'for columns size 10 status');
PL/SQL 过程已成功完成。
SQL> select count(*) from test where status='INVALID';
  COUNT(*)
----------
        14
执行计划
----------------------------------------------------------
Plan hash value: 680875269
------------------------------------------------------------------------------
| Id  | Operation         | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |          |     1 |     7 |       (0)| 00:00:01 |
|   1 |  SORT AGGREGATE   |          |     1 |     7 |            |          |
|*  2 |   INDEX RANGE SCAN| I_STATUS |     8 |    56 |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------
SQL> select count(*) from test where status='VALID';
  COUNT(*)
----------
     49947
执行计划
----------------------------------------------------------
Plan hash value: 1531502959
----------------------------------------------------------------------------------
| Id  | Operation             | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |          |     1 |     7 |    27   (8)| 00:00:01 |
|   1 |  SORT AGGREGATE       |          |     1 |     7 |            |          |
|*  2 |   INDEX FAST FULL SCAN| I_STATUS | 49948 |   341K|    27   (8)| 00:00:01 |
----------------------------------------------------------------------------------
SQL> drop index i_status ;
索引已删除。
SQL> create bitmap index i_b_status on test(status);
索引已创建。
SQL> select count(*) from test where status='VALID';
  COUNT(*)
----------
     49947
执行计划
----------------------------------------------------------
Plan hash value: 1410402464
--------------------------------------------------------------------------------------------
| Id  | Operation                     | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |            |     1 |     7 |     2   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE               |            |     1 |     7 |            |          |
|   2 |   BITMAP CONVERSION COUNT     |            | 49948 |   341K|     2   (0)| 00:00:01 |
|*  3 |    BITMAP INDEX FAST FULL SCAN| I_B_STATUS |       |       |            |          |
--------------------------------------------------------------------------------------------
可以看到bitmap(cost=2)的查询效率确实比B*tree(cost=27)效率高很多。
现在我们来看看bitmap对于DML的影响。
在三个session中同时执行
insert into test select * from dba_objects where rownum<2;
我这里就不贴了,我们看看ASH,看看v$session_wait,v$session.
SQL> select sid,username,program,event from v$session where username is not null;
       SID USERNAME                       PROGRAM                                                          EVENT
---------- ------------------------------ ---------------------------------------------------------------- ----------------------------------------------------------------
       143 ROBINSON                       plsqldev.exe                                                     SQL*Net message from client
       144 ROBINSON                       plsqldev.exe                                                     enq: TX - row lock contention
       146 ROBINSON                       plsqldev.exe                                                     SQL*Net message from client
       159 ROBINSON                       sqlplus.exe                                                      enq: TX - row lock contention
可以看到在sqlplus,plsqldev中分别发生了TX-row lock contention竞争,这个竞争就是由于刚才执行的
insert into test select * from dba_objects where rownum<2;引起的。
如果你不相信,我用ASH给你查找出来
SQL> select session_id,event,count(*),sum(time_waited) from v$active_session_history where  session_state='WAITING'
  2  and time_waited>0 and sample_time>=(sysdate-&howlongago/(24*60))
  3  group by session_id,event order by 3 desc;

SESSION_ID EVENT                                                              COUNT(*) SUM(TIME_WAITED)
---------- ---------------------------------------------------------------- ---------- ----------------
       144 enq: TX - row lock contention                                           146        435563478
       159 enq: TX - row lock contention                                           138        414017496
       167 db file parallel write                                                    7            64316
       165 control file parallel write                                               5            63539
       143 enq: TX - row lock contention                                             4         10362621
       166 log file parallel write                                                   2           133521
       165 control file sequential read                                              1            86807
       164 db file sequential read                                                   1            26782
       146 db file sequential read                                                   1              572
9 rows selected
SQL> select event, session_id,sql_id, p1,p2,p3 from v$active_session_history where sample_time>=(sysdate-&howlongago/(24*60)) and session_id=&sid;
EVENT                                                            SESSION_ID SQL_ID                P1         P2         P3
---------------------------------------------------------------- ---------- ------------- ---------- ---------- ----------
enq: TX - row lock contention                                           144 9n78yftyyayk1 1415053316     196632        978
enq: TX - row lock contention                                           144 9n78yftyyayk1 1415053316     196632        978
enq: TX - row lock contention                                           144 9n78yftyyayk1 1415053316     196632        978
............................................................................省略.....................................................................
498 rows selected
ASH 是 每隔1s收集一次统计信息,我这里查询除了498条,意思就是说等待了498秒,而且现在还在等待,我估计我不kill其中的一个session
永远都,那么那两个会话将永远等待。
SQL> select sql_text from v$sqlarea where sql_id='&sql_id';
SQL_TEXT
--------------------------------------------------------------------------------
insert into test select * from dba_objects where rownum<2
由此证明,引起TX-row lock contention就是 上面的那条insert语句.
此时你除了kill其中一个session,别无办法。
只有2,3个人并发的去操作某一个表,就发生了TX lock,如果并发再高点,估计整个表都无法用,在刚才那张表中,由于status只有valid和invalid两个值,当一条insert 执行的时候,如果status是valid的,由于要更新bitmap,需要lock status=valid的所有行,所以千万别在oltp中使用bitmap index 。

posted on 2009-12-16 15:45  如果蜗牛有爱情  阅读(183)  评论(0编辑  收藏  举报

导航