Oracle基於函數的索引

  • 基於函數的索引
    比如執行如下一條SQL語句:select * from emp where upper(ename) = ‘KING’,即使在ename上建立了索引,還是會全表掃描emp表,將裏面的ename字段改成大寫跟常量KING進行比較。如果我們建立一個基於函數的索引,比如:create index emp_upper_idx on emp(upper(ename)); 這個時候,我們只需要按區間掃描小部分數據,然後獲取rowid取訪問表中的數據,這個速度是比較快的。
    基於函數的索引,類似於普通的索引,只是普通的索引是建立在列上,而它是建立在函數上。當然這回對插入數據有一定影響,因爲需要通過函數計算一下,然後生成索引。但是插入數據一般都是少量插入,而查詢數據一般數據量比較大。爲了優化查詢速度,稍微降低點插入速度是可以承擔的。
    函數索引還有一個功能,只對部分行建立索引。假設有一個很大的表,有一列叫做FLAG,只可能取Y和N。假設大部分數據是Y,小部分數據是N,我們需要將N修改成Y。如果建立一個普通索引,這個索引會非常大,而且將N修改成Y的時候,維護這個索引開銷會很大。不過這個表聽起來比較適合位圖索引,但這是一個事物系統(OLTP),可能有很多人同時插入記錄,或者進行修改。那麼位圖索引也不適合。所以,如果我們只是在值爲N的行上建立索引,就比較好辦了。
    只在值爲N的行建立索引SQL:create index flag_index on big_table(case flag when ‘N’ then ‘N’ end);這樣一個索引大小會大大降低,而且維護成本也會很低的。前提是我們只對值爲N的行感興趣。

  • 位圖索引
    位圖索引的適用條件
    位圖索引適合只有幾個固定值的列,如性別、婚姻狀況、行政區等等,而身份證號這種類型不適合用位圖索引。
    位圖索引適合靜態數據,而不適合索引頻繁更新的列。

舉個例子,有這樣一個字段busy,記錄各個機器的繁忙與否,當機器忙碌時,busy爲1,當機器不忙碌時,busy爲0。

這個時候有人會說使用位圖索引,因爲busy只有兩個值。好, 我們使用位圖索引索引busy字段!假設用戶A使用update更新某個機器的busy值,比如update table set table.busy=1 where rowid=100;,但還沒有commit,而用戶B也使用update更新另一個機器的busy值,update table set table.busy=1 where rowid=12; 這個時候用戶B怎麼也更新不了,需要等待用戶A commit。

原因:用戶A更新了某個機器的busy值爲1,會導致所有busy爲1的機器的位圖向量發生改變,因此數據庫會將busy=1的所有行鎖定,只有commit之後才解鎖。

問題: 爲什麼更新了某個機器的busy值爲1,會導致所有busy爲1的機器的位圖向量發生改變,因此數據庫會將busy=1的所有行鎖定?

答案請看位圖索引的存儲結構。

位圖的存儲,位圖中位的個數和表中的記錄數項目,

比如下面婚姻狀況表
姓名(Name) 性別(Gender) 婚姻狀況(Marital)
張三 男 已婚
李四 女 已婚
王五 男 未婚
趙六 女 離婚
孫七 女 未婚

表中有5行記錄,所以創建的記錄會有5位
性別列-男的位圖: 10100
性別列-女的位圖: 01011
已婚列的位圖: 11000
未婚列的位圖: 11000
離婚列的位圖: 11000
所以現在知道了吧, 當要更新位圖索引時,就要更新這個位圖,那麼將會鎖定整個位圖或者要更新的這個位所在的塊。

發佈了70 篇原創文章 · 獲贊 20 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章