熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Oracle >> 正文

位圖索引的故事

2013-11-13 22:16:35  來源: Oracle 

  您如果熟悉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有這麼強大的功能呢!


From:http://tw.wingwit.com/Article/program/Oracle/201311/18656.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.