ORA-01502 oracle資料庫 index索引的兩種形式,ora-01502oracle
目前的項目中,我們在跑批次的時候,有個SP總是報錯 “ORA-01502: index 'WBILL_102.PK_A_NOTWEB_ACT_PROVINCE_M' or partition of such index is in unusable state” ,解決辦法就是重建索引,ALTER INDEX IN_AA REBUILD;
但是解決完之後,在跑批還是報這個錯誤,這就讓我需要考慮,產生這個問題的原因是什麼!
我的錯誤情境還原:
有個表 CUS_ASSET_MONTH,主鍵是 PK_CUS_ASSET_MONTH ,主鍵欄位是 CUS_CODE,這個表 是分區表 ,分區欄位是 DATA_YM
為了使得我們的批次有重跑的功能,所以批次的第一步驟都是 將本月的資料刪除:
ALTER TABLE CUS_ASSET_MONTH TRUNCATE PARTITION PA_CUS_ASSET_MONTH_201412;
然後在往表 CUS_ASSET_MONTH 中 insert ,這個時候就會報錯 ORA-01502
情境還原完畢!
問題分析:
CUS_ASSET_MONTH 表的索引 PK_CUS_ASSET_MONTH 是全域索引,
這是建立索引的語句:
alter table CUS_ASSET_MONTH add constraint PK_CUS_ASSET_MONTH primary key (cus_code) using index ;
這樣建立的索引,預設是 GLOBAL INDEX
在對 表分區進行 TRUNCATE 操作之後,在進行 insert 就會報錯 ORA-01502 。
所以我們需要將 索引改成 LOCAL INDEX
alter table CUS_ASSET_MONTH add constraint PK_CUS_ASSET_MONTH primary key (cus_code) using index LOCAL ;
但是在執行這句話的時候,又報錯了:ORA-14039:分區列必須構成UNIQUE索引的關鍵字列子集
因為這是建立的是主鍵索引,主鍵索引的欄位在分區表中必須要包含分區欄位,如果這個主鍵索引必須要有,那麼可以將這個主鍵索引改成一個普通索引。
我的最終解決辦法[主鍵也有,普通索引也有]:
alter table CUS_ASSET_MONTH add constraint PK_CUS_ASSET_MONTH primary key (cus_code,data_ym) using index LOCAL ;
create index IN_CUS_ASSET_MONTH ON CUS_ASSET_MONTH(cus_code) local;
這樣我在對錶分區進行 TRUNCATE 操作之後,在往這個表中插入資料的時候,就不會再報錯了!
PS 局部索引LOCAL INDEX 和 全域索引GLOBAL INDEX 的區別 :
局部索引local index
1. 局部索引一定是分區索引,分區鍵等同於表的分區鍵,分區數等同於表的分區說,一句話,局部索引的分區機制和表的分區機制一樣。
2. 如果局部索引的索引列以分區鍵開頭,則稱為首碼局部索引。
3. 如果局部索引的列不是以分區鍵開頭,或者不包含分區鍵列,則稱為非首碼索引。
4. 首碼和非首碼索引都可以支援索引分割區消除,前提是查詢的條件中包含索引分割區鍵。
5. 局部索引只支援分區內的唯一性,無法支援表上的唯一性,因此如果要用局部索引去給表做唯一性限制式,則約束中必須要包括分區鍵列。
6. 局部分區索引是對單個分區的,每個分區索引只指向一個表分區,全域索引則不然,一個分區索引能指向n個表分區,同時,一個表分區,也可能指向n個索引分割區,
對分區表中的某個分區做truncate或者move,shrink等,可能會影響到n個全域索引分割區,正因為這點,局部分區索引具有更高的可用性。
7. 位元影像索引只能為局部分區索引。
8. 局部索引多應用於資料倉儲環境中。
全域索引global index
1. 全域索引的分區鍵和分區數和表的分區鍵和分區數可能都不相同,表和全域索引的分區機制不一樣。
2. 全域索引可以分區,也可以是不分區索引,全域索引必須是首碼索引,即全域索引的索引列必須是以索引分割區鍵作為其前幾列。
3. 全域分區索引的索引條目可能指向若干個分區,因此,對於全域分區索引,即使只動,截斷一個分區中的資料,都需要rebulid若干個分區甚
至是整個索引。
4. 全域索引多應用於oltp系統中。
5. 全域分區索引只按範圍或者散列hash分區,hash分區是10g以後才支援。
6. oracle9i以後對分區表做move或者truncate的時可以用update global indexes語句來同步更新全域分區索引,用消耗一定資源來換取高度的可用性。
7. 表用a列作分區,索引用b做局部分區索引,若where條件中用b來查詢,那麼oracle會掃描所有的表和索引的分區,成本會比分區更高,此時可以考慮用b做全域分區索引
分區索引字典
DBA_PART_INDEXES 分區索引的概要統計資訊,可以得知每個表上有哪些分區索引,分區索引的類新(local/global,)
Dba_ind_partitions每個分區索引的分區級統計資訊
Dba_indexesminusdba_part_indexes,可以得到每個表上有哪些非分區索引
索引重建
Alter index idx_name rebuild partition index_partition_name [online nologging]
需要對每個分區索引做rebuild,重建的時候可以選擇online(不會鎖定表),或者nologging建立索引的時候不組建記錄檔,加快速度。
Alter index rebuild idx_name [online nologging]
對非分區索引,只能整個index重建