Oracle中關於bitmap index的使用問題

您若是熟悉 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

相關文章
相關標籤/搜索