27.读书笔记收获不止Oracle之 位图索引更新

前端之家收集整理的这篇文章主要介绍了27.读书笔记收获不止Oracle之 位图索引更新前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

27.读书笔记收获不止Oracle之 位图索引更新

新建立一个会话,查看会话号:

sql> select sid from v$mystat whererownum=1;

SID

----------

42

关于表t,查看上一篇

sql> insert into t(name_id,gender,location,age_group,data) values(100001,'m',45,'child',rpad('*',20,'*'));

1 row created.

不进行提交。

然后新开一个会话

sql> select sid from v$mystat where rownum=1;

SID

----------

72

在新会话中,插入一行

sql> insert into t(name_id,data) values(100002,46,'*'));

导致直接卡主。

再换一个会话链接

sql>select sid from v$mystat where rownum=1;

SID

----------

24

插入如下:

sql>insert into t(name_id,data)values (100003,'f',47,'middle_age','*'));

可以插入。

可以发现,gender列仅是m和f两种取值。某SESSSION插入该表的记录是m,其他任何SESSION与m相关的记录就不能插入。

此外,DELETE和UPDATE都不能更新位图索引所在的列。

1. 位图索引使用场景

位图在即席查询方面独领风骚,但是对更新确实一场灾难。

位图索引使用两个条件:1、位图索引列大量重复,2、表极少更新。

1.1重复度低情况

Drop table t purge;

Create table t as select * fromdba_objects;

Insert into t select * from t;

Insert into t select * from t;

Insert into t select * from t;

Update t set object_id=rownum;

Commit;

然后建立位图索引

sql>create bitmap indexidx_bit_object_id on t(object_id);

sql>set autotrace traceonly

sql>select count(*) from t;

Execution Plan

----------------------------------------------------------

Plan hash value: 2966233522

-------------------------------------------------------------------

| Id| Operation | Name | Rows | Cost (%cpu)| Time |

-------------------------------------------------------------------

| 0| SELECT STATEMENT | | 1 |426 (1)| 00:00:01 |

| 1| SORT AGGREGATE | | 1 | | |

| 2| TABLE ACCESS FULL| T |90945 | 426 (1)| 00:00:01 |

-------------------------------------------------------------------

Statistics

----------------------------------------------------------

1recursive calls

0 dbblock gets

12411 consistent gets

0physical reads

0 redosize

544 bytes sent via sql*Net to client

551 bytes received via sql*Net from client

2sql*Net roundtrips to/from client

0sorts (memory)

0sorts (disk)

1 rowsprocessed

在OBJECT_ID列建了位图索引后,ORACLE不选择这个索引而走全表扫描。

强制走索引,看看:

sql> select /*+index(t,idx_bit_object_id)*/ count(*) from t;

Execution Plan

----------------------------------------------------------

Plan hash value: 2130576087

--------------------------------------------------------------------------------------

| Id| Operation | Name | Rows| Cost (%cpu)| Time |

--------------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 1 | 2540 (1)| 00:00:01 |

| 1| SORT AGGREGATE | | 1| | |

| 2| BITMAP CONVERSION COUNT| | 90945 | 2540 (1)| 00:00:01 |

| 3| BITMAP INDEX FULL SCAN|IDX_BIT_OBJECT_ID | | | |

--------------------------------------------------------------------------------------

Statistics

----------------------------------------------------------

1recursive calls

0 dbblock gets

2536 consistent gets

2535 physical reads

0 redosize

544 bytes sent via sql*Net to client

551 bytes received via sql*Net from client

2sql*Net roundtrips to/from client

0sorts (memory)

0sorts (disk)

1 rowsprocessed

发现使用这个位图索引后,代价比全表扫描要高很多。

但是全表扫描的逻辑读比位图索引扫描大很多。

当然 COST代价是更准确的,因为除了IO还有cpu等开销。

1.2真相

加入t表有4个字段,分别是ID、NAME、SEX和STATUS。SEX仅为男或女。

如下图1

当在SEX列建立位图索引时候,

索引建值只有三个不同的取值,

位图索引存储的是比特位值,例如SEX性别列只有男,整个位图索引的大小大致等于行数乘以这1个比特。位图索引在重复度很高时,体积非常小,COUNT(*) 统计非常快。

如果对OBJECT_ID这个不重复列建位图索引,那么位图索引大小瞬间增大几百万倍。从中获取条数肯定没有优势了。

猜你在找的Oracle相关文章