BlogJava-bruceleey's columns -随笔分类-数据库http://www.blogjava.net/invoked/category/41850.htmlIt's better to burn out, than fade away.zh-cnSat, 19 Dec 2009 11:27:20 GMTSat, 19 Dec 2009 11:27:20 GMT60Oracle编程高手箴言:位图索引(Bitmap Index)的故事http://www.blogjava.net/invoked/archive/2009/12/18/306603.html张晓枫张晓枫Fri, 18 Dec 2009 10:21:00 GMThttp://www.blogjava.net/invoked/archive/2009/12/18/306603.htmlhttp://www.blogjava.net/invoked/comments/306603.htmlhttp://www.blogjava.net/invoked/archive/2009/12/18/306603.html#Feedback0http://www.blogjava.net/invoked/comments/commentRss/306603.htmlhttp://www.blogjava.net/invoked/services/trackbacks/306603.html导读:

  您如果熟悉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





本文转自

http://blog.csdn.net/carlwu/archive/2008/04/24/2319584.aspx


张晓枫 2009-12-18 18:21 发表评论
]]>
110个Oracle常用函数总结(备查 )http://www.blogjava.net/invoked/archive/2009/12/03/304629.html张晓枫张晓枫Thu, 03 Dec 2009 07:16:00 GMThttp://www.blogjava.net/invoked/archive/2009/12/03/304629.htmlhttp://www.blogjava.net/invoked/comments/304629.htmlhttp://www.blogjava.net/invoked/archive/2009/12/03/304629.html#Feedback0http://www.blogjava.net/invoked/comments/commentRss/304629.htmlhttp://www.blogjava.net/invoked/services/trackbacks/304629.html阅读全文

张晓枫 2009-12-03 15:16 发表评论
]]>
Oracle连接数过多释放机制http://www.blogjava.net/invoked/archive/2009/09/26/296532.html张晓枫张晓枫Sat, 26 Sep 2009 06:48:00 GMThttp://www.blogjava.net/invoked/archive/2009/09/26/296532.htmlhttp://www.blogjava.net/invoked/comments/296532.htmlhttp://www.blogjava.net/invoked/archive/2009/09/26/296532.html#Feedback0http://www.blogjava.net/invoked/comments/commentRss/296532.htmlhttp://www.blogjava.net/invoked/services/trackbacks/296532.html  
  通过profile可以对用户会话进行一定的限制,比如IDLE时间。
将IDLE超过一定时间的会话断开,可以减少数据库端的会话数量,减少资源耗用。


使用这些资源限制特性,需要设置resource_limit为TRUE:
[oracle@test126 udump]$ sqlplus "/ as sysdba"

SQL*Plus: Release 10.2.0.1.0 - Production on Fri Oct 13 07:58:21 2006

Copyright (c) 1982, 2005, Oracle.  All rights reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning and Data Mining options

SQL> show parameter resource

NAME                                TYPE        VALUE
------------------------------------ ----------- ------------------------------
resource_limit                      boolean    TRUE
resource_manager_plan                string

该参数可以动态修改:
SQL> alter system set resource_limit=true;

System altered.

数据库缺省的PROFILE设置为:
SQL> SELECT * FROM DBA_PROFILES;

PROFILE              RESOURCE_NAME                    RESOURCE LIMIT
-------------------- -------------------------------- -------- ---------------
DEFAULT              COMPOSITE_LIMIT                  KERNEL  UNLIMITED
DEFAULT              SESSIONS_PER_USER                KERNEL  UNLIMITED
DEFAULT              CPU_PER_SESSION                  KERNEL  UNLIMITED
DEFAULT              CPU_PER_CALL                    KERNEL  UNLIMITED
DEFAULT              LOGICAL_READS_PER_SESSION        KERNEL  UNLIMITED
DEFAULT              LOGICAL_READS_PER_CALL          KERNEL  UNLIMITED
DEFAULT              IDLE_TIME                        KERNEL  UNLIMITED
DEFAULT              CONNECT_TIME                    KERNEL  UNLIMITED
DEFAULT              PRIVATE_SGA                      KERNEL  UNLIMITED
DEFAULT              FAILED_LOGIN_ATTEMPTS            PASSWORD 10
DEFAULT              PASSWORD_LIFE_TIME              PASSWORD UNLIMITED

PROFILE              RESOURCE_NAME                    RESOURCE LIMIT
-------------------- -------------------------------- -------- ---------------
DEFAULT              PASSWORD_REUSE_TIME              PASSWORD UNLIMITED
DEFAULT              PASSWORD_REUSE_MAX              PASSWORD UNLIMITED
DEFAULT              PASSWORD_VERIFY_FUNCTION        PASSWORD NULL
DEFAULT              PASSWORD_LOCK_TIME              PASSWORD UNLIMITED
DEFAULT              PASSWORD_GRACE_TIME              PASSWORD UNLIMITED

16 rows selected.

创建一个允许3分钟IDLE时间的PROFILE:
SQL> CREATE PROFILE KILLIDLE LIMIT IDLE_TIME 3;

Profile created.

新创建PROFILE的内容:
SQL> col limit for a10
SQL> select * from dba_profiles where profile='KILLIDLE';

PROFILE                        RESOURCE_NAME                    RESOURCE LIMIT
------------------------------ -------------------------------- -------- ----------
KILLIDLE                      COMPOSITE_LIMIT                  KERNEL  DEFAULT
KILLIDLE                      SESSIONS_PER_USER                KERNEL  DEFAULT
KILLIDLE                      CPU_PER_SESSION                  KERNEL  DEFAULT
KILLIDLE                      CPU_PER_CALL                    KERNEL  DEFAULT
KILLIDLE                      LOGICAL_READS_PER_SESSION        KERNEL  DEFAULT
KILLIDLE                      LOGICAL_READS_PER_CALL          KERNEL  DEFAULT
KILLIDLE                      IDLE_TIME                        KERNEL  3
KILLIDLE                      CONNECT_TIME                    KERNEL  DEFAULT
KILLIDLE                      PRIVATE_SGA                      KERNEL  DEFAULT
KILLIDLE                      FAILED_LOGIN_ATTEMPTS            PASSWORD DEFAULT
KILLIDLE                      PASSWORD_LIFE_TIME              PASSWORD DEFAULT

PROFILE                        RESOURCE_NAME                    RESOURCE LIMIT
------------------------------ -------------------------------- -------- ----------
KILLIDLE                      PASSWORD_REUSE_TIME              PASSWORD DEFAULT
KILLIDLE                      PASSWORD_REUSE_MAX              PASSWORD DEFAULT
KILLIDLE                      PASSWORD_VERIFY_FUNCTION        PASSWORD DEFAULT
KILLIDLE                      PASSWORD_LOCK_TIME              PASSWORD DEFAULT
KILLIDLE                      PASSWORD_GRACE_TIME              PASSWORD DEFAULT

16 rows selected.

测试用户:
SQL> select username,profile from dba_users where username='EYGLE';

USERNAME                      PROFILE
------------------------------ --------------------
EYGLE                          DEFAULT

修改eygle用户的PROFILE使用新建的PROFILE:
SQL> alter user eygle profile killidle;

User altered.

SQL> select username,profile from dba_users where username='EYGLE';

USERNAME                      PROFILE
------------------------------ --------------------
EYGLE                          KILLIDLE

进行连接测试:
[oracle@test126 admin]$ sqlplus eygle/eygle@eygle

SQL*Plus: Release 10.2.0.1.0 - Production on Fri Oct 13 08:07:13 2006
Copyright (c) 1982, 2005, Oracle.  All rights reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning and Data Mining options

SQL> select username,profile from dba_users where username='EYGLE';

USERNAME                      PROFILE
------------------------------ ------------------------------
EYGLE                          KILLIDLE


当IDLE超过限制时间时,连接会被断开:
SQL> select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;

TO_CHAR(SYSDATE,'YY
-------------------
2006-10-13 08:08:41

SQL> select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual
*
ERROR at line 1:
ORA-02396: exceeded maximum idle time, please connect again

张晓枫 2009-09-26 14:48 发表评论
]]>