【DB筆試面試352】什麼是不可用索引(Unusable Indexes),哪些操作會導致索引變為不可用即失效狀態?

  • 2019 年 10 月 10 日
  • 筆記

Q

題目

在Oracle資料庫中,什麼是不可用索引(Unusable Indexes),哪些操作會導致索引變為不可用(unusable)即失效狀態?

A

答案

(一)什麼是不可用索引(Unusable Indexes)?對於不可用索引需要注意哪些?

在正常情況下,索引都是可用的。對於可用的索引而言,DBA_INDEXES的STATUS列的值為VALID。當執行某些操作後,例如對索引執行MOVE操作,索引會變為不可用(unusable),即處於失效狀態。當索引變為不可用時,Oracle內部會把該索引元數據(即創建語句包含的基本資訊)與真實物理數據之間的對應關係撕裂,相關數據塊可被重用,相關的索引段會被刪除,DBA_INDEXES的SEGMENT_CREATED列的值會變為NO(正常情況下,應為YES),STATUS列的值變為UNUSABLE。對於失效的索引,若想要被重新使用,則只有一種方法,那就是REBUILD,當然也可以先DROP 再CREATE。

對於失效的索引需要注意以下幾點:

l 從Oracle 11gR2開始,當索引不可用時,Oracle會清除索引數據(刪除相關的索引段),並且不再維護。

l 在本地索引中,可以設置某個分區的索引為UNUSABLE。

l 一般情況下,CBO不考慮使用UNUSABLE狀態的索引,包含分區表。相關參數為SKIP_UNUSABLE_INDEXES,其作用如下所示:

參數作用

控制對UNUSABLE 的非唯一索引,DML操作時是否維護索引數據。

參數值

true | false

當參數設置為true時(默認),當資料庫遇到不可用索引時,只會忽略而不會提示任何錯誤資訊;同時即使該表上帶有不可用的索引或索引分區,也可以針對該表執行DML操作,針對不可用索引對應的DML語句都將正常執行,而且資料庫停止維護相關索引。在進行DML(INSERT和UPDATE)操作時,如果是唯一索引,那麼無論該參數的值設置為何值,Oracle都會去校驗索引的可用性。如果索引不可用,那麼就會報錯ORA-01502。

當參數設置為false時,DML操作及CBO生成執行計劃時都會考慮該索引。所有與UNUSABLE索引相關的操作都會失敗,報錯資訊為:ORA-01502: 索引 'SCOTT.INDEX_T2' 或這類索引的分區處於不可用狀態。

l 在重建索引的時候一般不允許DML操作,只有加上ONLINE的時候才允許DML操作。

(二)哪些操作會導致索引失效?

一般情況下,當某些操作導致數據行的ROWID改變後,索引就會完全失效,可以分普通表和分區表來討論哪些操作將導致索引失效。

(1)普通表索引失效的情形如下所示:

① 手動置索引無效:ALTER INDEX IND_OBJECT_ID UNUSABLE;。

② 如果對錶進行MOVE操作(包含移動表空間和壓縮操作)或在線重定義表後,那麼該表上所有的索引狀態會變為UNUSABLE。MOVE操作的SQL語句為:ALTER TABLE TT MOVE;。

③ SQL*Loader載入數據。

在SQL*Loader載入過程中會維護索引,由於數據量比較大,在SQL*Loader載入過程中出現異常情況,也會導致Oracle來不及維護索引,導致索引處於失效狀態,影響查詢和載入。異常情況主要有:在載入過程中殺掉SQL*Loader進程、重啟或表空間不足等。

(2)分區表索引失效的情形如下所示:

① 對分區表的某個含有數據的分區執行了TRUNCATE、DROP操作可以導致該分區表的全局索引失效,而分區索引依然有效,如果操作的分區沒有數據,那麼不會影響索引的狀態。需要注意的是,對分區表的ADD操作對分區索引和全局索引沒有影響。

② 執行EXCHANGE操作後,全局索引和分區索引都無條件地會被置為UNUSABLE(無論分區是否含有數據)。但是,若包含INCLUDING INDEXES子句(預設情況下為EXCLUDING INDEXES),則全局索引會失效,而分區索引依然有效。

③ 如果執行SPLIT的目標分區含有數據,那麼在執行SPLIT操作後,全局索引和分區索引都會被被置為UNUSABLE。如果執行SPLIT的目標分區沒有數據,那麼不會影響索引的狀態。

④ 對分區表執行MOVE操作後,全局索引和分區索引都會被置於無效狀態。

⑤ 手動置其無效:ALTER INDEX IND_OBJECT_ID UNUSABLE;。

對於分區表而言,除了ADD操作之外,TRUNCATE、DROP、EXCHANGE和SPLIT操作均會導致全局索引失效,但是可以加上UPDATE GLOBAL INDEXES子句讓全局索引不失效。重建分區索引的命令為:ALTER INDEX IDX_RANG_LHR REBUILD PARTITION P1;。

分區表的索引是否失效情況如下表所示:

目標分區有數據

目標分區無數據

操作動作

操作命令

全局索引

分區索引

是否失效

如何避免失效

是否失效

如何避免失效

TRUNCATE分區

ALTER TABLE PT_TRUNC_LHR TRUNCATE PARTITION P1;

失效

操作語句後加UPDATE GLOBAL INDEXES

沒影響

對全局索引和分區索引都沒有影響

DROP分區

ALTER TABLE PT_DROP_LHR DROP PARTITION P1;

沒影響

SPLIT分區

ALTER TABLE PT_SPLIT_LHR SPLIT PARTITION P_MAX AT (30000) INTO (PARTITION P3,PARTITION P_MAX);

如果MAX區中已經有記錄了,這個時候SPLIT就會導致有記錄的新增分區的局部索引失效!

對局部索引進行重建索引ALTER INDEX IDX_PART_SPLIT_COL3 REBUILD;

EXCHANGE分區

ALTER TABLE PT_EX_LHR EXCHANGE PARTITION P1 WITH TABLE T_NM_LHR INCLUDING INDEXES;

沒影響

和有數據時一致

ALTER TABLE PT_EX_LHR EXCHANGE PARTITION P1 WITH TABLE T_NM_LHR;

失效

對局部索引進行重建索引ALTER INDEX IDX_PART_EX_COL3 REBUILD;

ADD分區

ALTER TABLE PT_ADD_LHR ADD PARTITION P6 VALUES LESS THAN (6666);

對全局索引和分區索引都沒有影響

& 說明:

有關資料庫操作導致索引失效的更多內容可以參考我的BLOG:http://blog.itpub.net/26736162/viewspace-2152871/

Oracle之不可見索引 :http://blog.itpub.net/26736162/viewspace-2124044/

Oracle之虛擬索引 : http://blog.itpub.net/26736162/viewspace-2123687/

Oracle之不可見索引和虛擬索引的比對:http://blog.itpub.net/26736162/viewspace-2124164/