您如果熟悉
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
有这么强大的功能呢!”。
参考文献:
Thomas Kyte, 2005, Expert Oracle Database Architecture: 9i and 10g Programming Techniques and Solutions
分享到:
相关推荐
Linux 内核数据结构:位图(Bitmap) Linux 内核数据结构:位图(Bitmap) 位图是一种常用的数据结构,在 Linux 内核中大量使用。位图可以用来存储系统在线/离线处理器,来支持(CPU)热插拔;再比如,位图在 ...
oracle位图索引,讲解oracle的bitmap索引。
可以看出,位图索引`leo_bm_t1_index`的空间占用远小于B*树索引`leo_bm_t2_bt_index`。 ```sql SQL> col segment_name for a20 SQL> select segment_name, bytes 2 from user_segments 3 where segment_type = '...
**位图索引**(Bitmap Index)是一种特殊类型的索引,它使用位图来表示数据。每个位对应数据库表中的一个特定值,如果某个记录包含这个值,那么相应的位就被设置为1,否则为0。例如,如果表中有100万行,有三个不同...
C# 实现位图算法(BitMap) 位图算法(BitMap)是一种高效的数据结构,主要用于快速查询和存储大规模数据。下面将详细介绍 C# 中如何实现位图算法(BitMap)。 什么是 BitMap BitMap 的基本思想就是用一个 bit 位...
在VC++环境中,读取24位位图(Bitmap)是一项常见的图像处理任务。24位位图是一种颜色深度为24位的图像格式,它能够表示约1670万种颜色,提供了丰富的色彩表现力。MFC(Microsoft Foundation Classes)是微软提供的...
本文将深入探讨两种常见的索引结构:B树(Btree)和位图索引(Bitmap Index),并对比它们的特性和适用场景。 首先,我们来了解B树。B树是一种自平衡的多路搜索树,适用于大量数据的存储系统。它的每个节点可以有多...
- **位图索引(Bitmap Index)**: 适合于在含有大量重复值的列上,尤其是在进行多列组合查询时,将多个位图索引合并进行快速查找。 - **函数索引(Function-Based Index)**: 允许基于函数的结果创建索引,使得对...
- **位图段(Bitmap segment):** 由一系列位组成,若某位为1,则表示对应的行包含索引键值;若为0,则表示该行不含该键值。 **特点:** - Oracle使用专有压缩技术压缩位图段,以节省存储空间。 - 适用于低基数列...
位图联接索引(Bitmap Join Index):位图联接索引是针对多表联接查询优化的,它在一个表上创建位图索引,并将另一个表的值映射到这个位图索引上。在执行联接查询时,可以直接利用位图之间的运算来定位结果集,...
Maven坐标:org.roaringbitmap:RoaringBitmap:0.7.45; 标签:roaringbitmap、RoaringBitmap、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 ...
Oracle数据库是世界上最广泛使用的数据库系统之一,其性能优化的一个关键因素就是索引的使用。索引可以帮助快速查找和访问数据库中的数据,显著提高查询效率。本篇将详细讲解Oracle数据库中的索引及其重要性。 一、...
2. **位图索引(Bitmap Index)** 位图索引主要用于低基数(非唯一或重复值多)的列,将每个值用一个位来表示,节省空间,适合在并集查询中使用。 3. **反向索引(Reverse Index)** 反向索引主要应用于长文本...
4. **位图索引(Bitmap index)**:位图索引用位图表示索引键值,适合于低选择性(很多行具有相同的键值)的列,特别适用于联接操作和复杂的逻辑条件。 5. **位图联接索引(Bitmap Join Index)**:为多列联接操作优化...
1. 位图索引(Bitmap Index):位图索引适合于具有大量重复值的列,它将每个唯一的键值映射为一个位图,通过位运算快速找到匹配的行。位图索引在数据仓库和只读场景下效果显著,但在频繁更新的环境中可能会增加...
位图索引的创建语法为:create bitmap index 索引名 on 表名(列名)。位图索引可以合并简化查询条件,从而过滤被访问的数据集合。 簇索引是一种特殊类型的索引,适用于簇表。簇索引可以快速找到簇表中的记录。创建簇...