oracle的各種索引介紹

2021-08-27 07:42:55 字數 3820 閱讀 6113

索引:

最常用的索引包括:b*樹索引、位圖索引、位圖聯合索引、基於函式索引、應用域索引

1 b*書索引:實現快速定位,資料庫會根據所索引的列來建立索引,如果該列是唯一的就將該列進行排序,然後建立索引,如果該列不唯一則加入rowid列,使其達到唯一,然後進行排序

b*樹索引包括如下幾種:

普通索引

反向鍵索引:將索引列用reverse函式反序後建立索引,這是為了避免當同時插入資料太多,導致同乙個索引塊忙碌的情況,比如同時插入1w個記錄,這1w個記錄就會同時在乙個索引塊裡建立索引,導致該塊忙碌,影響效能

降序索引:索引預設是按照索引列遞增的順序進行排序的,如果索引列是遞減的也可以用預設的索引,畢竟倒過來就是遞減的;但是如果索引列有2個字段,而當我查詢的時候乙個是asc,乙個是desc,這時候預設索引到不到預期的效果;但是如果給遞減列用上降序索引,的增列用上預設索引的話,那麼效能會大幅提高;

關於聚簇因子:oracle有乙個表叫user_indexes,在這裡可以查詢所有的索引,比如執行查詢

select a.index_name,b.num_rows,b.blocks,a.clustering_factor from user_indexes a, user_tables b

where index_name in ('xx1','xx2') and a.table_name = b.table_name; 其中clustering_factor:聚簇因子 index_name索引名 num_rows:行數 blocks:資料塊

如果clustering_factor非常接近blocks,說明資料非常有序,連續的資料可能在乙個塊中,這樣進行區間段等大資料查詢的時候,效能越高

如果clustering_factor非常接近num_rows,說明資料非常隨即。索引條目指向的資料不一定在乙個快中,進行區間等查詢的時候,效能很差

b*樹索引應用場合:1 僅僅返回少數資料,資料重複度低;2 直接用索引能完成,沒有涉及到表(比如select count(x) where x='xx',這種語句直接檢索索引,根本接觸不到表本身,速度顯然很快)

2 位圖索引:對於頻繁更新的表,不適合建立位圖索引;位圖索引會記錄該列的資料1存放在1,3,4,7...行,資料2存放在2,5,6...行,資料null存放在8,9...行等等,會把所有資料及其位置都記錄下來;

所以,資料的重複度越高,越適合位圖索引;如何衡量呢,就是不同相資料的個數除以總行數越接近零越好;偽**:count(distinct(col))/count(*)越接近零,越適合做位圖索引;

以上資料不應該建立b*樹索引,因為b*樹是樹形結構,而重複度高的資料,會根據乙個值檢索到大量的資料。這違背了b*樹索引的原則。

如果進行查詢select count(*) from table1 where col1='x' or col1='y',這個就會用到位圖索引,只是將2個合併,都不會去查詢表,在索引中直接返回正確結果

如果進行查詢select * from table1 wwhere col1='x' or col1='y',這個會用到位圖索引,oracle會到位圖索引去找到所有x和y的索引,然後找到相應的rowid,然後根據rowid快速返回結果集

對於頻繁更新的表,為什麼不適合用位圖索引:乙個位圖索引中維護了乙個資料和多個行的位置,如果乙個會話修改了該列某一行的指定資料,比如xx1,那麼該位圖索引所維護的xx1資料的所有行都會被鎖定;oracle是無法鎖定乙個位圖索引中的某乙個行的。這樣就會出現如下問題:

如果該資料有100行,那麼更新一行的時候,100行資料均被鎖定,導致其他會話只能等待期釋放之後才能操作;如果頻繁出現這種情況的話,效能會嚴重下降。

3 位圖聯結索引:這是oracle9i所引入的乙個索引;對於關聯表建立位圖索引,比如有乙個部門表和員工表,員工表中存放了部門表的主鍵,此時想根據部門的name來查詢所有的員工,這是如果建立和點陣圖聯結索引,聚會很快得到結果集;

4 基於函式的索引(待續)

關於索引常見的問題:

1 檢視能建立索引嗎:檢視引用的是基本表,只需要對基本表建立索引,就相當於在檢視中建立索引;

2 null和索引的協作:

-- b*樹索引不能建立在都可以為null的列上,因為b*書索引會過濾掉null,也就是說,當進行查詢的時候:

比如在col1和col2上建立了索引,col1和col2都可以為空,查詢select * from table1 where col1 is null 這個語句不會使用索引,因為如果使用索引的話,可能會丟失資料(那些null的資料會丟失);因為索引無法建立在都可以為null的列上,oracle優化器會選擇不使用索引,而是全表掃瞄;

3 外來鍵是否可以建立索引:在以下情況中,最好在外鍵上建索引

a 如果經常進行聯機刪除或者修改父表主鍵的情況,建議在子表外來鍵上建立索引。如果不建立索引的話,有上述操作時,oracle會把整個子表全部鎖死,這也是oracle出現死鎖的情況,嚴重影響系統效能;

b 從父表查詢子表資訊的時候,比如根據deptname查詢該部門下所有員工資訊的時候,建議在子表外來鍵上建立索引,或者建立位圖聯結索引,否則如果頻繁進行上述查詢的話,速度會很慢,因為每次都對員工表進行了全表掃瞄。

4 索引為何失效

a 關於b*樹索引,如果是a、b兩列建立索引,如果a、b兩列都允許為空的話,由於在全是null的資料上不會建立索引,所以為了避免查詢資料不準確,優化器會放棄使用索引,而是使用全表掃瞄;

b 關於b*樹索引,如果是a、b兩列建立索引,如果這樣select * from table1 where b =5;此時如果a列的資料重複率不高的話,如果用索引的話,會去檢索每條索引的資料,這樣優化器更傾向於用全表掃瞄;如果a資料重複度很高,優化器會用一種跳躍式掃瞄方式,此時會用上索引;

c 如果用到了函式,比如select * from table1 where f(a) = xx;此時不會用到索引,因為索引是建立在a上的,而不是建立在f(a)上的;

d 如果a列是字元型別,但是我們執行了select * from table1 where a = 5;此時其實是隱式的應用了to_number(a)=5;索引是建立在a上,而不是建立在函式上的;

e 有些時候oracle的優化器會智慧型的判斷使用索引後是否會提高效率,如果不會提高效率那麼優化器會自動放棄索引,而執行full table;此時請檢查索引的合理性;

oracle程式設計藝術上說:歸根結底,原因通常就是

「不能使用索引,使用索引會返回不正確的結果」

「不應該使用索引,使用了,效能會變得很糟糕」

另外:如果是兩個列建立索引,那麼哪個放前面,哪個放後面呢:

這個要視情況而定,如果只有如下查詢select * from table1 where a= :x and b= :y,那麼哪個在前面都無所謂;

如果還有這種方式:select * from table1 where b = :y ,那麼需要b列在前面;

oracle程式設計藝術中還就索引壓縮做出對比,這裡不記錄了。以上都是個人理解記錄,都是為了方便自己。

跳躍式掃瞄

從oracle9i開始,索引跳躍式掃瞄特性可以允許優化器使用組合索引,即便索引的前導列沒有出現在where子句中。索引跳躍式掃瞄比全索引掃瞄要快的多。

下面的比較他們的區別:

sql> set timing on

sql> create index tt_index on tt(teamid,areacode);

索引已建立。

sql> select count(areacode) from tt;

count(areacode)

---------------

7230369

sql> select /*+ index(tt tt_index )*/ count(areacode) from tt;

count(areacode)

---------------

7230369

各種Oracle索引型別介紹

邏輯上 single column 單行索引 concatenated 多行索引 unique 唯一索引 nonunique 非唯一索引 function based函式索引 domain 域索引 物理上 partitioned 分割槽索引 nonpartitioned 非分割槽索引 b tree ...

各種Oracle索引型別介紹

邏輯上 single column 單行索引 concatenated 多行索引 unique 唯一索引 nonunique 非唯一索引 function based函式索引 domain 域索引 物理上 partitioned 分割槽索引 nonpartitioned 非分割槽索引 b tree ...

ORACLE索引介紹

什麼是索引 索引是建立在表的一列或多個列上的輔助物件,目的是加快訪問表中的資料 oracle儲存索引的資料結構是b 樹,位圖索引也是如此,只不過是葉子節點不同b 數索引 索引由根節點 分支節點和葉子節點組成,上級索引塊包含下級索引塊的索引資料,葉節點包含索引資料和確定行實際位置的rowid。使用索引...