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

1 基本概念

位图索引(bitmap index)技术是一类特殊的数据库索引技术,其索引使用bit数组(或称bitmap、bit set、bit string、bit vector)进行存储与计算操作。

1.1. 什么是位图索引?

位图索引是从oracle 7.3版本开始引入的。目前oracle企业版和个人版都支持位图索引,但是标准版不支持。位图索引是这样一种结构,其中用一个索引键条目存储指向多行的指针,这与B树结构不同,在b树结构中,索引键和表中的行存在着对应关系。在位图索引中,可能只有很少的索引条目,每个索引条目指向多行,而在传统的B*树中,一个索引条目就指向一行那么什么是位图索引呢?(借用网络的例子讲解)

2. 表现形式

有张表名为table的表,由三列组成,分别是姓名、性别和婚姻状况,其中性别只有男和女两项,婚姻状况由已婚、未婚、离婚这三项,该表共有100w个记录。现在有这样的查询:

select * from table where Gender=‘男’ and Marital=“未婚”;
姓名(Name) 性别(Gender) 婚姻状况(Marital)
张三 已婚
李四 已婚
王五 未婚
赵六 离婚
孙七 未婚
  1. 不使用索引

不使用索引时,数据库只能一行行扫描所有记录,然后判断该记录是否满足查询条件。

  1. B树索引

对于性别,可取值的范围只有’男’,‘女’,并且男和女可能各站该表的50%的数据,这时添加B树索引还是需要取出一半的数据, 因此完全没有必要。相反,如果某个字段的取值范围很广,几乎没有重复,比如身份证号,此时使用B树索引较为合适。事实上,当取出的行数据占用表中大部分的数据时,即使添加了B树索引,数据库如oracle、mysql也不会使用B树索引,很有可能还是一行行全部扫描。

  1. 位图索引

位图索引创建了之后,生成是位图数据可以这么理解,比如,男女两种,然后一共八条数据,那么就生产两个字符串,一个代表男,一个代表女,字符串长度为数据的总数量,字符串的值:第一位(如果第一条数据是男那么就是1,如果不是就0),第二位,第三位,往后都是这样。由此就生成了长度为总数量,只包含01的字符串,通过这个字符串就能知道第几条数据是男,第几条不是男,同理,另外一条代表女的字符串也一样,是女的就1,不是女的就0。

如果用户查询的列的基数非常的小, 即只有的几个固定值,如性别、婚姻状况、行政区等等。要为这些基数值比较小的列建索引,就需要建立位图索引。

对于性别这个列,位图索引形成两个向量,男向量为10100…,向量的每一位表示该行是否是男,如果是则位1,否为0,同理,女向量位01011。

RowId 1 2 3 4 5
1 0 1 0 0
0 1 0 1 1

对于婚姻状况这一列,位图索引生成三个向量,已婚为11000…,未婚为00100…,离婚为00010…。

RowId 1 2 3 4 5
已婚 1 1 0 0 0
未婚 0 0 1 0 1
离婚 0 0 0 1 0

当我们使用查询语句“select * from table where Gender=‘男’ and Marital=“未婚”;”的时候 首先取出男向量10100…,然后取出未婚向量00100…,将两个向量做and操作,这时生成新向量00100…,可以发现第三位为1,表示该表的第三行数据就是我们需要查询的结果。

当我们使用查询语句“select * from table where Gender=‘男’ and Marital=“未婚”;”的时候 首先取出男向量10100…,然后取出未婚向量00100…,将两个向量做and操作,这时生成新向量00100…,可以发现第三位为1,表示该表的第三行数据就是我们需要查询的结果。

RowId 1 2 3 4 5
1 0 1 0 0
and
未婚 0 0 1 0 1
结果 0 0 1 0 0

3. 位图索引的创建

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

create bitmap index emp_job_bitmap_idx on emp(job);

4. 位图索引的原理

  1. 索引块的一个索引行中存储键值、起止Rowid,以及这些键值的位置编码,
  2. 位置编码中的每一位表示键值对应的数据行的有无.位数=表的总记录数
  3. 所需的位图个数=索引列的不同键值多少,列的不同值越少,所需的位图就越少
  4. 当根据键值查询时,可以根据起始Rowid和位图状态,快速定位数据.
  5. 这样与B*树那样直接保存rowid的区别就在于每次都要进行rowid的换算工作。

4.1. 例子说明

CREATE TABLE EMP (EMPNO NUMBER (4) PRIMARY KEY,ENAME VARCHAR2 (10),JOB VARCHAR2 (9),MGR NUMBER (4),HIREDATE DATE,SAL NUMBER (7, 2),COMM NUMBER (7, 2),DEPNO NUMBER (4)
);
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

create bitmap index emp_job_bitmap_idx on emp(job);
SELECT EMPNO,ENAME,SAL FROM EMP WHERE JOB = 'SALESMAN';

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

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

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

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

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

4.2. 位图索引与数据DML锁定

Bitmap测试

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

OLTP与OLAP是什么?: https://blog.csdn.net/joshho/article/details/117357700

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

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

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

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 。尽管他们修改的不是同一列。

Session1提交

Session2 阻塞解除,自动执行了

5. 位图索引的特点

5.1 Bitmap索引的存储空间更小

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

  1. 表的总记录数
  2. 索引列的键值多少,列的不同值越少,所需的位图就越少.

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相互操作都会发锁定。

6. 什么情况下应该使用位图索引?

  1. 位图索引适合只有几个固定值的列,如性别、婚姻状况、行政区等等,而身份证号这种类型不适合用位图索引,如果用户查询的列的相异基数非常的小, 要为这些相异基数值比较小的列建索引,就需要建立位图索引。

那么何谓相异基数非常的小?可以认为行集中不同项的个数除以行数应该是一个很小的数(接近0),例如,某个列(性别)可能取值为M、F、null.如果一个表中有20000条数据,那么3/20000=0.00015,那么这就算是个相异基数很小的情况,类似的,如果有100000个不同的值,与10000000条结果相比,比值是0.01,同样也很小,也可以认为是相异基数很小的情况,都可以建立位图索引;

  1. 这个时候有人会说使用位图索引,因为busy只有两个值。好,我们使用位图索引索引busy字段!假设用户A使用update更新某个机器的busy值,比如update table set table.busy=1 where rowid=100;,但还没有commit,而用户B也使用update更新另一个机器的busy值,update table set table.busy=1 where rowid=12; 这个时候用户B怎么也更新不了,需要等待用户A commit。

原因:用户A更新了某个机器的busy值为1,会导致所有busy为1的机器的位图向量发生改变,因此数据库会将busy=1的所有行锁定,只有commit之后才解锁。

7. 位图索引的限制或者说是弊端?

位图索引在读密集的环境中能很好地工作,但是对于写密集的环境则极不适合,原因在于,一个位图索引键条目(可以理解为前面的男 、女、未婚、已婚等)指向多行。如果一个会话修改了有索引的列的数据,那么大多数情况下,这个索引条目只想的所有行都会被锁定。oracle无法锁定一个位图索引条目中的单独一位,而是会锁定整个位图索引条目,倘若其他会话修改也需要更新同样的这个位图索引条目,就会被“关在门外”,这样就大大影响了并发性,因为每个更新都有可能锁定数百行,不允许并发地更新他们的位图列;

举个例子说明:有这样一个字段job,记录各个员工的职位如:dba 、java、php等等 ,假设我们在这个job列上建立了位图索引。假如rowid=100的员工职业为php,rowid=120的员工职业为php;

如果会话1使用update更新某个员工的职位(job),比如update table set table.job=‘dba’ where rowid=100;,但还没有commit,而会话2也使用update更新另一个员工的职位,update table set table.job=‘dba’ where rowid=120; 这个时候会话2怎么也更新不了,需要等待会话1 commit。

原因:会话1更新rowid=100的这个员工的职位,假如这个员工原来是php,现在改成dba,那么在commit之前,就会锁定所有job=php和job=dba的所有行,所以当会话2尝试更新job=dba只能等待锁,只有commit之后才解锁。这样就大大影响了并发性;

8. 总结:

位图索引是为数据仓库(也就是查询环境设计的),位图索引特别不适合OLTP系统,位图索引不适合与dml频繁的环境,位图索引适用于DSS系统,位图索引不适合频繁修改的系统,弊端是严重影响

并发性,因为update索引列值的时候,会锁定新值和旧值指向的所有数据行,所以使用位图索引需慎重。

数据库索引:位图索引相关推荐

  1. oracle 函数位图索引,位图索引

    常规的B树索引对包含每行记录的ROWID与索引键值.位图索引不会直接存储ROWID,每个不同的键值都有一个位图,这就是为什么创建位图索引的列要有较少的distinct值的原因.位图中的每一位映射到一个 ...

  2. Oracle索引----位图索引

    位图索引(bitmap index)是从Oracle7.3版本开始引入的.目前Oracle企业版和个人版都支持位图索引,但标准版不支持.位图索引是为数据仓库/即席查询环境设计的,在此所有查询要求的数据 ...

  3. 位图索引,数据库索引浅浅的学习

    摘自http://www.cnblogs.com/LBSer/p/3322630.html 位图(BitMap)索引 前段时间听同事分享,偶尔讲起Oracle数据库的位图索引,顿时大感兴趣.说来惭愧, ...

  4. mysql实现位图索引_位图索引,数据库索引浅浅的学习

    位图(BitMap)索引 前段时间听同事分享,偶尔讲起Oracle数据库的位图索引,顿时大感兴趣.说来惭愧,在这之前对位图索引一无所知,因此趁此机会写篇博文介绍下位图索引. 1. 案例 有张表名为ta ...

  5. Oracle 位图索引

    内容简介: 1.位图索引 1.1位图索引使用注意事项; 1.2 使用位图索引; 1.3 位图索引对DML操作的影响; 2.位图连接索引 2.1 明确需求后使用位图索引; 2.1创建位图连接索引的注意事 ...

  6. mysql bitmap index_位图索引:原理(BitMap index)

    位图(BitMap)索引 前段时间听同事分享,偶尔讲起Oracle数据库的位图索引,顿时大感兴趣.说来惭愧,在这之前对位图索引一无所知,因此趁此机会写篇博文介绍下位图索引. 1. 案例 有张表名为ta ...

  7. 达梦数据库和mysql索引引擎_达梦数据库如何建索引和使用

    一.建立索引的准则 1.1在表中插入数据后创建索引 一般情况下,在插入或装载了数据后,为表创建索引会更加有效率.如果在装载数据之前创建了一个或多个索引,那么在插入每行时DM数据库都必须更改和维护每个索 ...

  8. 【索引分类】位图索引

    位图索引 位图索引非常适合于决策支持系统(Decision Support System,DSS)和数据仓库,它们不应该用于通过事务处理应用程序访问的表.它们可以使用较少到中等基数(不同值的数量)的列 ...

  9. 达梦数据库简介及索引创建

    前言: 武汉达梦数据库股份有限公司成立于2000年,为中国电子信息产业集团(CEC)旗下基础软件企业,致力于数据库管理系统与大数据平台的研发.销售和服务,同时可为用户提供全栈数据产品和解决方案.多年来 ...

  10. oracle索引图解,oracle 位图索引详解

    一.什么是位图索引 我们目前大量使用的索引一般主要是B*Tree索引,在索引结构中存储着键值和键值的RowID,并且是一一对应的. 而位图索引主要针对大量相同值的列而创建(例如:类别,操作员,部门ID ...

最新文章

  1. Nature癌症“牵线木偶”理论:科学家找到了不易误伤健康细胞的“剪刀”
  2. oracle导入dmp方法,oracle dmp文件导入方法
  3. matlab simulink 电气连接
  4. Spring Boot怎么样注册Servlet三大组件[Servlet、Filter、Listener]
  5. 6.组函数(avg(),sum(),max(),min(),count())、多行函数,分组数据(group by,求各部门的平均工资),分组过滤(having和where),sql优化
  6. MongoDB数据库使用总结
  7. Disruptor并发框架-1
  8. 庐山真面-Oxite的HelloWorld
  9. python(1) - 数据类型和变量
  10. 从语义开始 – 概念、意义、实践
  11. 开源身份证识别_新的开源:金钱,公司和身份
  12. Kubernetes详解(五)——Kubernetes核心对象
  13. MyBatis(二)------使用JDBC编程问题总结
  14. 远程视频监控之硬件篇
  15. EOS主网上线,如何在Imtoken里导入EOS钱包?
  16. Mybatis源码分析(一) | 如何调试Mybatis源码
  17. nginx-1.13.7 按照centos8 报错记录
  18. AutoCAD2014官方原版软件下载
  19. 【邢不行|量化小讲堂系列48-实战篇】听说今天融资盘爆仓了?来看看融资数据在量化投资中的作用
  20. 发送短信(SMS)承载方式有哪些?

热门文章

  1. Android 高德地图搜索功能相关
  2. java求阶乘1-20_java求1+2!+3!+...+20!的和,java1到20的阶乘
  3. 梳理需求-需求调研报告
  4. 德标螺纹规格对照表_德标DIN934六角螺母,不锈钢六角螺母DIN934
  5. python游戏编程实战教程_关于游戏编程的详细介绍
  6. Python实现多重弹窗脚本 整蛊朋友
  7. DSP应用技术(第一章)
  8. RS485通讯介绍(附批量测试思路)
  9. 成功解决问题[xml:[xX][mM][lL] is not allowed
  10. (附源码)计算机毕业设计SSM旅游网站设计