您若是熟悉 Oracle 数据库,我想您对 Thomas Kyte 的大名必定不会陌生。 Tomas 主持的 asktom.oracle.com 网站享誉 Oracle 界数十年,绝非幸致。最近在图书馆借到这位 Oracle 绝顶高手编著的《 Expert Oracle Database Architecture-9i and 10g programming Techniques and Solutions 》,翻阅之下,果真盛名无虚,虽说不上字字珠玑,但做者对 Oracle 架构的理解和实践确实已达到出神入化的境界。若是您有时间和兴趣,强烈建议您阅读这本书。这本书最大的特色是语言生动活泼,说理清楚,几乎每讲解一个原理,做者都给出了具体实例,让人读起来绝不气闷。linux
另外, Thomas 谦逊的态度让我很是佩服, Thomas 在 Oracle 数据库方面工做了 16 年,而且参与了早期 Oracle 版本的开发,但他仍然谦虚地说,他天天都能从 Oracle 文档里学到新的东西。程序员
下面从这本书里摘录了一些精彩片断,供您欣赏,虽然难免有断章取义之嫌。sql
位图索引 (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 字段上创建位图索引呢? oracle
其中有一个开发者振振有词的说,这是为了提升查找速度,一旦创建了位图索引,咱们的程序就能快速找到那些数值为 N 的记录,而后处理。随后,他又拿出一本大部头的 Oracle 数据库参考手册,对 Tom 同志说,这书上都是这么说的,对那些数值很是少的字段,好比,咱们的 PROCESS_FLAG 字段只有两个值,就应该创建位图索引,这难道有什么问题吗? app
Tom 同志微微一笑,没有直接回答。只见他打开 SQL Plus ,链接到他的本地 Oracle 实例,给这群开发者演示了下面及其简单的 SQL 代码。 less
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