热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

Oracle中关于bitmapindex的使用问题

您如果熟悉Oracle数据库,我想您对ThomasKyte的大名一定不会陌生。Tomas主持的asktom.oracle.com网站享誉Oracle界数十

您如果熟悉 Oracle 数据库,我想您对 Thomas Kyte 的大名一定不会陌生。 Tomas 主持的 asktom.oracle.com 网站享誉 Oracle 界数十

您如果熟悉 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 有这么强大的功能呢!”。

linux

推荐阅读
  • 利用存储过程构建年度日历表的详细指南
    本文将介绍如何使用SQL存储过程创建一个完整的年度日历表。通过实例演示,帮助读者掌握存储过程的应用技巧,并提供详细的代码解析和执行步骤。 ... [详细]
  • SQLite 动态创建多个表的需求在网络上有不少讨论,但很少有详细的解决方案。本文将介绍如何在 Qt 环境中使用 QString 类轻松实现 SQLite 表的动态创建,并提供详细的步骤和示例代码。 ... [详细]
  • MySQL 数据库迁移指南:从本地到远程及磁盘间迁移
    本文详细介绍了如何在不同场景下进行 MySQL 数据库的迁移,包括从一个硬盘迁移到另一个硬盘、从一台计算机迁移到另一台计算机,以及解决迁移过程中可能遇到的问题。 ... [详细]
  • 探讨如何真正掌握Java EE,包括所需技能、工具和实践经验。资深软件教学总监李刚分享了对毕业生简历中常见问题的看法,并提供了详尽的标准。 ... [详细]
  • PHP 5.2.5 安装与配置指南
    本文详细介绍了 PHP 5.2.5 的安装和配置步骤,帮助开发者解决常见的环境配置问题,特别是上传图片时遇到的错误。通过本教程,您可以顺利搭建并优化 PHP 运行环境。 ... [详细]
  • 自学编程与计算机专业背景者的差异分析
    本文探讨了自学编程者和计算机专业毕业生在技能、知识结构及职业发展上的不同之处,结合实际案例分析两者的优势与劣势。 ... [详细]
  • 深入理解Java泛型:JDK 5的新特性
    本文详细介绍了Java泛型的概念及其在JDK 5中的应用,通过具体代码示例解释了泛型的引入、作用和优势。同时,探讨了泛型类、泛型方法和泛型接口的实现,并深入讲解了通配符的使用。 ... [详细]
  • 作为一名程序员,从大学步入职场后,常常感受到一种难以言喻的空虚感。这种感觉或许源于对生活的不满、职业发展的瓶颈,或是日常琐事带来的压力。本文将深入探讨这种复杂的情感,并尝试寻找解决之道。 ... [详细]
  • 深入解析:阿里实战 SpringCloud 微服务架构与应用
    本文将详细介绍 SpringCloud 在微服务架构中的应用,涵盖入门、实战和案例分析。通过丰富的代码示例和实际项目经验,帮助读者全面掌握 SpringCloud 的核心技术和最佳实践。 ... [详细]
  • 并发编程:深入理解设计原理与优化
    本文探讨了并发编程中的关键设计原则,特别是Java内存模型(JMM)的happens-before规则及其对多线程编程的影响。文章详细介绍了DCL双重检查锁定模式的问题及解决方案,并总结了不同处理器和内存模型之间的关系,旨在为程序员提供更深入的理解和最佳实践。 ... [详细]
  • 本文深入探讨了C++对象模型中的一些细节问题,特别是虚拟继承和析构函数的处理。通过具体代码示例和详细分析,揭示了书中某些观点的不足之处,并提供了更合理的解释。 ... [详细]
  • 随着网络安全威胁的不断演变,电子邮件系统成为攻击者频繁利用的目标。本文详细探讨了电子邮件系统中的常见漏洞及其潜在风险,并提供了专业的防护建议。 ... [详细]
  • 微软Exchange服务器遭遇2022年版“千年虫”漏洞
    微软Exchange服务器在新年伊始遭遇了一个类似于‘千年虫’的日期处理漏洞,导致邮件传输受阻。该问题主要影响配置了FIP-FS恶意软件引擎的Exchange 2016和2019版本。 ... [详细]
  • 深入理解Spring:Aware接口、异步编程与计划任务
    本文将带你深入了解Spring框架中的 Aware 接口、异步编程以及计划任务。通过具体示例和详细解释,帮助你掌握这些核心功能的实现原理和应用场景。 ... [详细]
  • TechStride 网站
    TechStride 成立于2014年初,致力于互联网前沿技术、产品创意及创业内容的聚合、搜索、学习与展示。我们旨在为互联网从业者提供更高效的新技术搜索、学习、分享和产品推广平台。 ... [详细]
author-avatar
泉州多棱汽车销售服务有限公司
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有