您如果熟悉 Oracle 数据库,我想您对 Thomas Kyte 的大名一定不会陌生。 Tomas 主持的 asktom.oracle.com 网站享誉 Oracle 界数十年,绝非幸致。最近在图书馆借到这位 Oracle 绝顶高手编著的《 Expert Oracle Database Architecture-9i and 10g programming Techniques and Solutions 》,翻阅之下,果然盛名无虚,虽然说不上字字珠玑,但作者对 Oracle 架构的理解和实践确实已达到出神入化的境界。如果您有时间和兴趣,强烈建议您阅读这本书。这本书最大的特点是语言生动活泼,说理清楚,几乎每讲解一个原理,作者都给出了具体实例,让人读起来毫不气闷。

另外, Thomas 谦逊的态度让我非常佩服, Thomas 在 Oracle 数据库方面工作了 16 年,并且参与了早期 Oracle 版本的开发,但他仍然谦虚地说,他每天都能从 Oracle 文档里学到新的东西。

下面从这本书里摘录了一些精彩片段,供您欣赏,虽然不免有断章取义之嫌。

位图索引 (Bitmap Index) 的故事

一日,一群 Java 开发者找到 Tom 先生,说他们新开发的系统已经上线,但性能及其低下,他们问 Tom 先生能不能替他们看看问题到底出在什么地方。他们告诉 Tom ,他们的系统采用 JSP+EJB+Oracle 的典型三层架构,其中 EJB 中的 SQL 是由第三方工具产生的。 Tom 同志一听到 EJB ,就知道这个系统是不能采用 SQL 代码跟踪的方法来进行性能调优了。于是, Tom 同志告诉这些心急火燎的 Java 开发者,你们系统的问题肯定在浏览器到数据库之间,但具体问题出在什么地方,我需要看看你们的数据库。

于是, Tom 同志远程连接到他们的测试数据库(注意不是生产数据库),查看了几个动态性能视图 (V$LOCK 和 V$SQL) ,最后终于发现了问题的所在。 Tom 同志发现他们的数据库中有一个位图索引 (Bitmap Index) 最为可疑,这个索引是建立在一个 PROCESS_FLAG 的字段上。 PROCESS_FLAG 字段表示该记录是否被处理了,可能值只有两个,一个是未处理 (N) ,一个是已经处理 (Y) 。当记录初次插入数据库时,该字段的值为 N ,但其它进程读取并处理那些未处理的记录 ( 值为 N 的记录 ) 后,这个字段的值就更新为 Y 。

Tom 就问这些 Java 开发者,你们为什么要在这个 PROCESS_FLAG 字段上建立位图索引呢?

其中有一个开发者振振有词的说,这是为了提高查找速度,一旦建立了位图索引,我们的程序就能快速找到那些数值为 N 的记录,然后处理。随后,他又拿出一本大部头的 Oracle 数据库参考手册,对 Tom 同志说,这书上都是这么说的,对那些数值非常少的字段,比如,我们的 PROCESS_FLAG 字段只有两个值,就应该建立位图索引,这难道有什么问题吗?

Tom 同志微微一笑,没有直接回答。只见他打开 SQL Plus ,连接到他的本地 Oracle 实例,给这群开发者演示了下面及其简单的 SQL 代码。

C:/Documents and Settings/carlwu>sqlplus scott/tiger@carl
SQL*Plus: Release 11.1.0.6.0 - Production on Wed Apr 23 18:15:34 2008
Copyright (c) 1982, 2007, Oracle.  All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL> create table t(processed_flag varchar2(1));
Table created.
SQL> create bitmap index t_idx on t(processed_flag);
Index created.
SQL> insert into t values('N');
1 row created.
SQL>

刚才那位振振有词的开发者不服气的说,这有什么,不是很正常吗?接着 Tom 又打开了一个 SQL Plus 窗口,并连接到本地数据库,键入下面的 SQL 语句,奇怪的是这条 SQL 并不执行,而是一直在等待。下面是这条 SQL 的一个截图:

这些 Java 开发者看到这里,惊讶得目瞪口呆。其中一个开发者犹豫地说,好象这个位图索引只允许一个用户操作,如果其它用户想同时操作这个索引,那他必须等第一个用户的请求处理完成,并且提交之后,才能进行,如果第一个用户不提交,那么他必须一直等待。 Tom 点头表示赞同,然后给他们作了一番详细的解释:

Oracle 数据库的位图索引 (Bitmap Index) 确实是针对那些数值稀疏 (low-cardinality , 低基数 ) 的字段,但是还应记住的一点是,它是针对那些 值不经常改变的 字段的。在实际应用中,如果某个字段的值需要频繁更新,那么就不适合在它上面创建位图索引。在位图索引中,如果你更新或插入其中一条数值为 N的记录,那么相应表中数值为 N的记录(可能成百上千条)全部被 Oracle锁定,这就意味着其它用户不能同时更新这些数值为 N的记录,其它用户必须要等第一个用户提交后,才能获得锁,更新或插入数据。

问题找到了,修正就很简单了, Tom建议这些开发者去掉了这个位图索引,然后在 PROCESS_FLAG 字段上建立一个函数索引,只为那些数值为 N 的记录建立简单的 B 树索引就可以了。

这些开发者回去后,按照 Tom 的指点,经过一番测试,终于解决了问题。

但故事并没有到此结束,这些开发者并不满足,他们给 Tom 写 email 抱怨道, Oracle 数据库真“烂”,连这个简单的位图索引问题都不能处理,你看, Oracle 浪费了我们大量的时间和精力调试我们的 Java 程序。 Tom 给他们回了一封 email ,颇有感触地对他们说:

I have encountered issues such as this many times when an application is being moved from database A to database B. When an application that worked flawlessly in database A does not work, or works in an apparently bizarre fashion, on database B, the first thought is that database B is “bad” database. The simple truth is that database B just works differently. Neither database is wrong or “bad; they are just different. Knowing and understanding how they both work will help you immensely in dealing with these issues.

( 当人们把一个应用从一种数据库迁移到另一种数据库时,他们常常抱怨同样的问题。本来这个应用程序在数据库 A 上运行得很好,当迁移到数据库 B 时,就出问题了。于是他们就认定,数据库 B 真烂。但事实并非如此,这只是因为数据库 B 的工作方式和原理不同于数据库 A 而已。世界上没有哪个数据库是“烂”数据库,关键是我们必须深入了解该数据库的架构和特点 ,这样才能避免这类问题。如果您理解位图索引的适用条件,您还会说 Oracle 是一个很“烂“的数据库吗? )

最后, Tom乘机 建议他们,如果你们愿意,我可以给你们做一次简单的为期 3 天的培训。这些 Java 程序员听从了 Tom 同志的建议,经过了 3 天的培训后,他们对 Oracle 能做的事情表示吃惊,他们纷纷表示,“我真傻,原来 Oracle 不适合建立临时表呀,你看我的程序老是在那里删除和创建临时表。”,“要是我用了物化视图 (Materalized View) ,我的数据备份代码就异常简单了。”,“我还不知道 connect by 有这么强大的功能呢!”。

文章转自:http://www.linuxidc.com/Linux/2011-10/45487.htm

Oracle中关于bitmap index的使用问题的更多相关文章

  1. Oracle中synonym和index

    笔记: Oracle-同义词--通过用户名(模式名).表名       --授权:grant create synonym to test1(system用户下授权))     --私有  creat ...

  2. oracle中,约束、表名、Index等的名称长度限制最大只能30个字符

    oracle中,约束.表名.Index等的名称长度限制最大只能30个字符

  3. Oracle分区表之分区范围扫描(PARTITION RANGE ITERATOR)与位图范围扫描(BITMAP INDEX RANGE SCAN)

    一.前言: 一开始分区表和位图索引怎么会挂钩呢?可能现实就是这么的不期而遇:比如说一张表的字段是年月日—‘yyyy-mm-dd’,重复率高吧,适合建位图索引吧,而且这张表数据量也不小,也适合转换成分区 ...

  4. Oracle中分区表的使用

       查询分区:Select *From user_extents WHERE partition_name='分区名'; 1)创建表空间 create tablespace HRPM0 datafi ...

  5. Oracle中的索引详解

    Oracle中的索引概述 索引与表一样,也属于段(segment)的一种.里面存放了用户的数据,跟表一样需要占用磁盘空间.索引是一种允许直接访问数据表中某一数据行的树型结构,为了提高查询效率而引入,是 ...

  6. [转]Oracle中的索引详解

    原文地址:http://www.oschina.net/question/30362_4057 一. ROWID的概念 存储了row在数据文件中的具体位置:64位 编码的数据,A-Z, a-z, 0- ...

  7. Oracle中HWM与数据库性能的探讨

    Oracle中HWM与数据库性能的探讨 一.什么是高水位 HWM(high water mark),高水标记,这个概念在segment的存储内容中是比较重要的.简单来说,HWM就是一个segment中 ...

  8. oracle 中的truncate 和delete

    一.查询表大小,块多少语句 Select SEGMENT_Name,BYTES,BLOCKS,Extents From dba_segments Where segment_name In('BAI_ ...

  9. [每日一题] 11gOCP 1z0-052 :2013-09-27 bitmap index.................................................C37

    转载请注明出处:http://blog.csdn.net/guoyjoe/article/details/12106027 正确答案C 这道题目是需要我们掌握位图索引知识点. 一.首先我们来看位图索引 ...

随机推荐

  1. 如何高效部署前端代码,如css,js...

    看了网上一些文章,做了点总结,顺便再加点自己的东西,简单的说下. 1.利用浏览器的304缓存,但是304叫协商缓存,还是需要与服务器通信一次 2.强制使用浏览器使用本地缓存(cache-control ...

  2. php中的字符串常用函数(三) str_replace() 子字符串替换

    mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] ); 该函数返回一个字 ...

  3. UltraEdit打开UTF-8文件后显示中文乱码的问题

    左图是UE,默认的编码格式GBK.右图可以看出可修改成UTF-8编码.按钮位置是UE底部状态栏,图3显示怎么开关状态栏. >>>>>>>>>> ...

  4. Java中的GOF23(23中设计模式)--------- 工厂模式(Factory)

    Java中的GOF23(23中设计模式)--------- 工厂模式(Factory) 在给大家介绍工厂模式之前,我想和大家聊聊面向对象的那点事,在这里,引入三个概念. 开闭原则(Open Close ...

  5. expect入门--自动化linux交互式命令

    很多linux程序比如passwd,ftp,scp,ssh等自身并没有提供一种静默式的执行选项,而是依赖于运行时的终端输入来进行后一步的操作比如更改密码.文件上传.下载等.虽然有些编程语言如java嵌 ...

  6. .NET WinForm画树叶小程序

    看了一片文章(http://keleyi.com/a/bjac/nurox416.htm),是使用分型画树叶,代码是Java的,因为Java很久没弄了,改用C#实现,下载地址: 画树叶小程序下载 核心 ...

  7. GitHub上我收藏Java及Android的项目Demo

    接触编程不久但浏览频率最高的还是GitHub毕竟它真的是程序员必不可少的新世界. (2016/9/23更新) 静态更新,很强势你值得拥有 更新资源不需要重新安装APK (2016.9.10更新) ht ...

  8. 在SqlServer中使用Try Catch(转)

    今天在写sql中出现了!我想在sql使用trycatch吧! 哎..但是语法又记不住了! 那就清楚我们的google大师吧! 嘿,网上关于在sql中使用Try Catch的还有真不少的文章! 闲话就少 ...

  9. Android 在外部存储读写文件

    本文主要介绍android中如何在外部存储读写数据 sd卡的路径 sdcard:2.3之前的sd卡路径 mnt/sdcard:4.3之前的sd卡路径 storage/sdcard:4.3之后的sd卡路 ...

  10. IOS 杂笔-4(属性与成员变量的区别)

    属性可以用点语法,比如self.xxx,在外部调用也同样可以someClass.xxx. 属性实际上是对一组set和get方法的简单封装(oc的get方法没有get前缀),同样会自动生成一个私有的成员 ...