您如果熟悉Oracle数据库我想您对ThomasKyte的大名一定不会陌生Tomas主持的网站享誉Oracle界数十年绝非幸致最近在图书馆借到这位Oracle绝顶高手编着的《ExpertOracleDatabaseArchitectureiandgprogrammingTechniquesandSolutions》翻阅之下果然盛名无虚虽然说不上字字珠玑但作者对Oracle架构的理解和实践确实已达到出神入化的境界如果您有时间和兴趣强烈建议您阅读这本书这本书最大的特点是语言生动活泼说理清楚几乎每讲解一个原理作者都给出了具体实例让人读起来毫不气闷 另外Thomas谦逊的态度让我非常佩服Thomas在Oracle数据库方面工作了年并且参与了早期Oracle版本的开发但他仍然谦虚地说他每天都能从Oracle文档里学到新的东西 下面从这本书里摘录了一些精彩片段供您欣赏虽然不免有断章取义之嫌 位图索引(BitmapIndex)的故事 一日一群Java开发者找到Tom先生说他们新开发的系统已经上线但性能及其低下他们问Tom先生能不能替他们看看问题到底出在什么地方他们告诉Tom他们的系统采用JSP+EJB+Oracle的典型三层架构其中EJB中的SQL是由第三方工具产生的Tom同志一听到EJB就知道这个系统是不能采用SQL代码跟蹤的方法来进行性能调优了于是Tom同志告诉这些心急火燎的Java开发者你们系统的问题肯定在浏览器到数据库之间但具体问题出在什么地方我需要看看你们的数据库 于是Tom同志远程连接到他们的测试数据库(注意不是生产数据库)查看了几个动态性能视图(V$LOCK和V$SQL)最后终于发现了问题的所在Tom同志发现他们的数据库中有一个位图索引(BitmapIndex)最为可疑这个索引是建立在一个PROCESS_FLAG的字段上PROCESS_FLAG字段表示该记录是否被处理了可能值只有两个一个是未处理(N)一个是已经处理(Y)当记录初次插入数据库时该字段的值为N但其它进程读取并处理那些未处理的记录(值为N的记录)后这个字段的值就更新为Y Tom就问这些Java开发者你们为什么要在这个PROCESS_FLAG字段上建立位图索引呢? 其中有一个开发者振振有词的说这是为了提高查找速度一旦建立了位图索引我们的程序就能快速找到那些数值为N的记录然后处理随后他又拿出一本大部头的Oracle数据库参考手册对Tom同志说这书上都是这么说的对那些数值非常少的字段比如我们的PROCESS_FLAG字段只有两个值就应该建立位图索引这难道有什么问题吗? Tom同志微微一笑没有直接回答只见他打开SQLPlus连接到他的本地Oracle实例给这群开发者演示了下面及其简单的SQL代码 C:\DocumentsandSettings\carlwu>sqlplusscott/tiger@carl SQL*Plus:ReleaseProductiononWedApr:: Copyright(c)OracleAllrightsreserved Connectedto: OracleDatabasegEnterpriseEditionReleaseProduction WiththePartitioningOLAPDataMiningandRealApplicationTestingoptions SQL>createtablet(processed_flagvarchar()); Tablecreated SQL>createbitmapindext_idxont(processed_flag); Indexcreated SQL>insertintotvalues(N); rowcreated SQL> 刚才那位振振有词的开发者不服气的说这有什么不是很正常吗?接着Tom又打开了一个SQLPlus窗口并连接到本地数据库键入下面的SQL语句奇怪的是这条SQL并不执行而是一直在等待下面是这条SQL的一个截图 这些Java开发者看到这里惊讶得目瞪口呆其中一个开发者犹豫地说好象这个位图索引只允许一个用户操作如果其它用户想同时操作这个索引那他必须等第一个用户的请求处理完成并且提交之后才能进行如果第一个用户不提交那么他必须一直等待Tom点头表示赞同然后给他们作了一番详细的解释 Oracle数据库的位图索引(BitmapIndex)确实是针对那些数值稀疏(lowcardinality低基数)的字段但是还应记住的一点是它是针对那些值不经常改变的字段的在实际应用中如果某个字段的值需要频繁更新那么就不适合在它上面创建位图索引在位图索引中如果你更新或插入其中一条数值为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乘机建议他们如果你们愿意我可以给你们做一次简单的为期天的培训这些Java程序员听从了Tom同志的建议经过了天的培训后他们对Oracle能做的事情表示吃惊他们纷纷表示我真傻原来Oracle不适合建立临时表呀你看我的程序老是在那里删除和创建临时表要是我用了物化视图(MateralizedView)我的数据备份代码就异常简单了我还不知道connectby有这么强大的功能呢! |