于位图索引相关的执行计划
admin
2023-05-11 09:41:36
0次

    位图索引是oracle数据库里除B树索引之外的另外一种索引的类型,它主要用于数据仓库或者DSS系统。在数据仓库或DSS系统中,针对某些类型的sql,用位图索引比用B树索引要快很多,这主要是位图索引实现了快捷的按位运算的缘故。

    位图索引的物理存储结构和普通B树索引的物理存储结构相似,也是按照被索引的键值列有序存储,只不过和索引键值一起存储的不再仅仅是索引键值所对应的rowid,而是变成了三部分的组合。这三部分分别为对应rowid的下限,对应rowid的上限和被压缩存储的位图(Bitmap Segment,位图段最大只能为位图索引叶子块大小的1/2),即oracle数据库中位图索引的物理存储结构:<被索引的键值,对应rowid的下限,对应rowid的上限,位图段>,这里位图段是压缩存储的,解压缩后就是一连串0和1的二进制位图序列,其中1表示被索引键值的一个有效rowid,oracle通过一个转换函数(mapping function)将解压缩段的位图段中的1结合对应rowid的上下限,转换为被索引键值所对应的有效rowid。

    上述位图索引的物理存储结构决定了oracle数据库中位图索引的锁粒度是在索引行的位图段上。对于oracle数据库的位图索引而言,它是没有行锁这个概念的,要锁就锁索引行的整个位图,而多个数据行可能对应同一索引的位图段。这种锁的粒度就决定了位图索引不适用于高并发频繁修改的OLTP系统,如果在高并发且频繁修改的OLTP系统中使用了位图索引,很可能会导致严重的并发问题,甚至会产生死锁。

    我们来看一个因为位图索引而导致常见的并发insert操作出现死锁的例子。创建一个测试表T1:

SQL> create table t1(id number,sex char(20));

Table created.

    在T1表中插入10000条数据:

SQL> begin

  2  for i in 1..5000 loop

  3  insert into  t1 values(i,'MALE');

  4  insert into t1 values(i,'FEMALE');

  5  end loop;

  6  end;

  7  /

PL/SQL procedure successfully completed.

    在T1的列SEX上创建一个位图索引IDX_BITMAP_T1:

SQL> create bitmap index idx_bitmap_t1 on t1(sex);

Index created.

    现在我们来构造死锁的情景,首先session 1中插入一条记录但不commit:

SQL> insert into t1 values(10001,'MALE');

1 row created.

    接着到session 2,插入一条记录但不commit:

SQL> insert into t1 values(10002,'FEMALE');

1 row created.

    回到session 1,再插入一条记录,这时这个插入操作hang住了:

SQL> insert into t1 values(10003,'FEMALE');--hang住

    再回到session 2,又插入一条记录,这时这个插入操作也hang住了:

    SQL> insert into t1 values(10004,'MALE');

    第2次回到session 1,这里oracle已经检测出了死锁:

SQL> insert into t1 values(10003,'FEMALE');

insert into t1 values(10003,'FEMALE')         *

ERROR at line 1:

ORA-00060: deadlock detected while waiting for resource

    这里的原理是当插入一条记录时,oracle需要去维护位图索引IDX_BITMAP_T1中所对应键值的位图段,因为记录数较少并且oracle是压缩存储位图段的缘故,所有sex值male的5000条记录对应的都是同一条索引行,sex值为female的5000条记录对应也是同一条索引行。这也意味着当插入一条新的sex值为male的那5000条记录);但插入一条新的sex值为female的记录时,oracle会锁原先所有sex值为female的那5000条记录所对应的位图段(即相当于锁了所有sex值为female的那5000条记录),所以通常情况下不会出现死锁的并发insert操作就这样出现了死锁。

    与B树索引相比,位图索引的优势主要体现在如下几个方面:

(1)因为位图索引的位图段的是压缩后存储的,所以如果被索引的distinct值较少,那么位图索引段与同列上的B树索引比起来,会显著节省空间。比如上例中表T的SEX列,其distinct 值仅为2,虽然表T1的数据量为10000,但SEX列上单键值位图索引idx_bitmap_t中只有两个索引行,而如果sex列上创建单键值B树索引,则显然该B树索引中的索引行的数量会是10000.

(2)如果需要再多个列上创建索引,那么位图索引与同等条件下的B树索引比起来,往往会显著节省存储空间。比如针对表CUSTOMER上的三列master_status,region和gender,用户可能会使用上述三列中任意单列或多列去访问表customer,如果此时要建B树索引,那么需要建三个复合B树索引(这里考虑到了复合B树索引可以代替单键值B树索引吗,三列复合B树索引可以代替两列复合B树索引)才能涵盖所有的情况,而如果是建位图索引的话,则只需要建三个针对上述三列的单键值位图索引就够了。

  (3)位图索引能够快速处理一些包含了各种AND或OR查询条件的sql,这主要是因为位图索引能够实现快捷的按位运算的缘故。

    关于位图索引能够实现快捷的按位运算的原理,我们用一个实例来说明。创建一个测试表customer:

SQL> create table customer(customer# number,marital_status varchar2(10),region varchar2(10),gender varchar2(10),income_level varchar2(10));

Table created.

    使用如下sql插入6条记录:

SQL> insert into customer values(101,'single','east','male','bracket_1');

1 row created.

SQL> insert into customer values(102,'married','central','female','bracket_4');

1 row created.

SQL> insert into customer values(103,'married','west','female','bracket_2');

1 row created.

SQL> insert into customer values(104,'divorced','west','male','bracket_4');

1 row created.

SQL> insert into customer values(105,'single','central','female','bracket_2');

1 row created.

SQL> insert into customer values(106,'married','central','female','bracket_3');

1 row created.

SQL> commit;

Commit complete.

    在列region上创建一个位图索引idx_b_region

SQL> create bitmap index idx_b_region on customer(region);

Index created.

    在列martial_status上创建另外一个位图索引idx_b_martialstatus:

SQL> create bitmap index idx_b_maritalstatus on customer(marital_status);

Index created.

    

SQL> select * from customer;

 CUSTOMER# MARITAL_ST REGION GENDER     INCOME_LEV

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

       101 single     east male    bracket_1

       102 married    central female     bracket_4

       103 married    west female     bracket_2

       104 divorced   west male    bracket_4

       105 single     central female     bracket_2

       106 married    central female     bracket_3

6 rows selected.


相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...