• 位图索引


         位图索引主要针对大量相同值的列而创建的索引。(例如:性别), 位图索引相对于传统的B*树索引,在叶子节点上采用了完全不同的结构组织方式。传统B*树索引将每一行记录保存为一个叶子节点,上面记录对应的索引列取值和行rowid信息。而位图索引将每个可能的索引取值组织为一个叶子节点。每个位图索引的叶子节点上,记录着索引键值、该索引键值的起始截止rowid和一个位图向量串。从本质上将,位图索引通过一个bit位来记录一个数据行是否存在对应键值。这种方式存储数据,相对于B*Tree索引,占用的空间非常小,创建和使用非常快. 这样做对比传统的B*树索引空间节省高。而且可以借助计算机位图运算的快速特性来提高索引结果利用率。

    一、位图索引的创建

    创建语法很简单,就是在普通索引创建的语法中index前加关键字bitmap即可,例如:

    create bitmap index emp_job_bitmap_idx on emp(job);

    二、位图索引的原理

    clip_image001

    1、 索引块的一个索引行中存储键值、起止Rowid,以及这些键值的位置编码,

    2、 位置编码中的每一位表示键值对应的数据行的有无.位数=表的总记录数

    3、 所需的位图个数=索引列的不同键值多少,列的不同值越少,所需的位图就越少

    4、 当根据键值查询时,可以根据起始Rowid和位图状态,快速定位数据.

    5、 这样与B*树那样直接保存rowid的区别就在于每次都要进行rowid的换算工作。

    三、例子

    以EMP表为例

     1 CREATE TABLE EMP (
     2     EMPNO NUMBER (4) PRIMARY KEY,
     3     ENAME VARCHAR2 (10),
     4     JOB VARCHAR2 (9),
     5     MGR NUMBER (4),
     6     HIREDATE DATE,
     7     SAL NUMBER (7, 2),
     8     COMM NUMBER (7, 2),
     9     DEPNO NUMBER (4)
    10 );

    插入数据

    INSERT INTO EMP VALUES (7369,'SMITH','CLERK',7902,to_date('17-12-1980','dd-mm-yyyy'),800,null,20);
    INSERT INTO EMP VALUES (7499,'ALLEN','SALESMAN',7698,to_date('20-2-1981','dd-mm-yyyy'),1600,300,30);
    INSERT INTO EMP VALUES (7521,'WARD','SALESMAN',7698,to_date('22-2-1981','dd-mm-yyyy'),1250,500,30);
    INSERT INTO EMP VALUES (7566,'JONES','MANAGER',7839,to_date('2-4-1981','dd-mm-yyyy'),2975,NULL,20);
    INSERT INTO EMP VALUES (7654,'MARTIN','SALESMAN',7698,to_date('28-9-1981','dd-mm-yyyy'),1250,1400,30);
    INSERT INTO EMP VALUES (7698,'BLAKE','MANAGER',7839,to_date('1-5-1981','dd-mm-yyyy'),2850,NULL,30);
    INSERT INTO EMP VALUES (7782,'CLARK','MANAGER',7839,to_date('9-6-1981','dd-mm-yyyy'),2450,NULL,10);
    INSERT INTO EMP VALUES (7839,'KING','PRESIDENT',NULL,to_date('17-11-1981','dd-mm-yyyy'),5000,NULL,10);
    INSERT INTO EMP VALUES (7844,'TURNER','SALESMAN',7698,to_date('8-9-1981','dd-mm-yyyy'),1500,0,30);
    INSERT INTO EMP VALUES (7900,'JAMES','CLERK',7698,to_date('3-12-1981','dd-mm-yyyy'),950,NULL,30);
    INSERT INTO EMP VALUES (7902,'FORD','ANALYST',7566,to_date('3-12-1981','dd-mm-yyyy'),3000,NULL,20);
    INSERT INTO EMP VALUES (7934,'MILLER','CLERK',7782,to_date('23-1-1982','dd-mm-yyyy'),1300,NULL,10);

    select distinct "JOB" from emp

    clip_image003

    创建位图索引

    create bitmap index emp_job_bitmap_idx on emp(job);

    查询

    SELECT EMPNO,ENAME,SAL FROM EMP WHERE JOB = 'SALESMAN';

    上述查询语句的目的是在EMP表中查询工作岗位是SALESMAN的员工的员工号,姓名和薪水,此时假设已经在EMP表的JOB列建立了位图索引,其结构如下图所示。

    clip_image005

    在该索引图中,共用5 类JOB,每类JOB 对应14 个比特位(对应14 行记录),其中某行的在该列的值与JOB 值对应则使用比特1 表示,如JOB = ‘CLERK’,第一行在该列对应的值是CLERK,就用比特1表示。否则用比特0表示,其他JOB类类似。

    clip_image007

    SELECT EMPNO,ENAME,SAL FROM EMP WHERE JOB = 'SALESMAN'

    通过位图索引扫描JOB=‘CLERK’对应的位图记录,找到值为1 的行记录,即找到需要查找数据。

    clip_image009

    (验证了每次都要进行rowid的换算工作)

    四、位图索引与数据DML锁定

    4.1 Bitmap测试

    用实验说明为什么位图索引不适合OLTP,比较适合OLAP。即:DML操作比较多的表不适合使用位图索引。

    以上面的EMP表为例,我们已经在该表的JOB字段建立了位图索引

    Session1:

    select distinct sid from v$mystat;
    
    UPDATE EMP SET JOB='CLERK' WHERE ENAME='ALLEN';

    clip_image011

    Session2

    select distinct sid from v$mystat;
    
    UPDATE EMP SET JOB='SALESMAN' WHERE ENAME='SMITH';

    clip_image013

    select * from v$lock where sid in(10,128) order by type;
    select sid,status,last_call_et,blocking_session from v$session where sid in(10,128);

    可以看见10阻塞了128 。尽管他们修改的不是同一列。

    clip_image015

    Session1提交

    clip_image017

    Session2 阻塞解除,自动执行了

    clip_image019

    4.2 B树索引测试。

    如果使用B树索引,就不存在阻塞情况了。创建同样的EMP表,使用EMPNO字段,英爱该字段为primary key,为B树索引。

    Session1

    SQL> select distinct sid from v$mystat;
    
    SID
    
    ----------
    
    10
    
    SQL> UPDATE EMP SET EMPNO=8000 WHERE ENAME='ALLEN';
    
    1 row updated.
    
    SQL>

    clip_image021

    Session2

    SQL> select distinct sid from v$mystat;
    
    SID
    
    ----------
    
    421
    
    SQL> UPDATE EMP SET EMPNO=9000 WHERE ENAME='SMITH';
    
    1 row updated.
    
    SQL>

    clip_image023

    select sid,status,last_call_et,blocking_session from v$session where sid in(10,421);

    两个窗口均为INACTIVE

    clip_image025

    五、位图索引的特点

    5.1 Bitmap索引的存储空间更小

    相对于B*Tree索引,位图索引由于只存储键值的起止Rowid和位图,占用的空间非常少. bitmap的空间占用主要与以下因素相关:

           a.表的总记录数

           b.索引列的键值多少,列的不同值越少,所需的位图就越少.

    5.2 Bitmap索引创建的速度更快

    位图索引创建时不需要排序, B*Tree索引则在创建时需要排序,定位等操作,速度要慢得多.

    5.3 Bitmap索引允许键值为空

    Bitmap索引允许键值为空 B*Tree索引由于不记录空值,当基于is null的查询时,会使用全表扫描, 而对位图索引列进行is null查询时,则可以使用索引.

    5.4 Bitmap索引对表记录的高效访问

    当使用count(XX),可以直接访问索引就快速得出统计数据.

    当根据位图索引的列进行and,or或 in(x,y,..)查询时,直接用索引的位图进行或运算,在访问数据之前可事先过滤数据.

    5.5 Bitmap索引对批量DML操作只需进行一次索引

    由于通过位图反映数据情况,批量操作时对索引的更新速度比B*Tree索引一行一行的处理快得多.

    5.6 Bitmap索引的锁机制

    对于B*Tree索引,insert操作不会锁定其它会话的DML操作. 而位图索引,由于用位图反映数据,不同会话更新相同键值的同一位图段,insert、update、delete相互操作都会发锁定。

    原文

    位图索引(Bitmap Index)——索引共用

    B树索引和位图索引的区别!

  • 相关阅读:
    237.Delete Node in a Linked List
    235.Lowest Common Ancestor of a Binary Search Tree
    234.Palindrome Linked List
    232.Implement Queue using Stacks
    231.Power of Two
    226.Invert Binary Tree
    225.Implement Stack using Queues
    Vue概述
    Git分布式版本控制工具
    分布式RPC框架Apache Dubbo
  • 原文地址:https://www.cnblogs.com/xqzt/p/4457184.html
Copyright © 2020-2023  润新知