【Oracle】ORA-01502の原因と解決方法|index or partition of such index is in unusable state

ORA-01502: index or partition of such index is in unusable state は、Oracleで UNUSABLE 状態のインデックス、またはインデックスパーティションを使おうとした時に発生するエラーです。索引が壊れているというより、Oracleが「このインデックスは現在使えない状態」と認識しているため、再構築や対象操作の見直しが必要です。

Oracle公式の説明でも、指定したインデックスまたはそのパーティションがUNUSABLE状態であることが原因とされています。対処は、対象インデックスを確認し、必要に応じて ALTER INDEX ... REBUILD またはパーティション単位のREBUILDを行う流れになります。

先に結論
ORA-01502が出たら、まず USER_INDEXES / DBA_INDEXESSTATUS = 'UNUSABLE' のインデックスを確認します。パーティション表なら USER_IND_PARTITIONS も見ます。その上で、通常インデックスなら ALTER INDEX ... REBUILD、パーティションインデックスなら対象パーティションをREBUILDします。
スポンサーリンク

ORA-01502とは

ORA-01502は、インデックスまたはインデックスパーティションがUNUSABLE状態で、SQL実行時にそのインデックスが必要になった時に出ます。特に、制約を支えるユニークインデックス、主キーインデックス、パーティション表のグローバルインデックスで業務影響が出やすいです。

インデックスの作成・再構築・削除の基本は インデックスの記事 も参考になります。この記事では、ORA-01502が出た直後の確認と復旧に絞って説明します。

通常インデックスがUNUSABLE

USER_INDEXES.STATUSUNUSABLE になっている状態です。通常はインデックス全体をREBUILDします。

パーティションインデックスがUNUSABLE

インデックス全体はVALIDでも、一部パーティションだけUNUSABLEになっていることがあります。

主キー/一意制約のインデックスがUNUSABLE

INSERTやUPDATEが失敗するなど、業務影響が大きくなりやすいです。

ALTER TABLE MOVE後に発生

表のMOVEやパーティション操作後にインデックスがUNUSABLEになることがあります。

まずUNUSABLEインデックスを確認する

最初に、対象スキーマ内でUNUSABLEになっているインデックスを確認します。自分のスキーマなら USER_INDEXES、管理者なら DBA_INDEXES を使います。

check-unusable-indexes.sql
SELECT index_name,
       table_name,
       status,
       uniqueness,
       partitioned
FROM user_indexes
WHERE status = 'UNUSABLE'
ORDER BY table_name, index_name;
check-unusable-indexes-dba.sql
SELECT owner,
       index_name,
       table_name,
       status,
       uniqueness,
       partitioned
FROM dba_indexes
WHERE status = 'UNUSABLE'
ORDER BY owner, table_name, index_name;

制約を支えるインデックスか確認する

UNUSABLEになっているインデックスが、主キー制約や一意制約を支えている場合は優先度が上がります。DMLが失敗したり、業務処理が止まったりするため、単なる性能劣化として扱わない方が安全です。

check-index-constraints.sql
SELECT c.constraint_name,
       c.constraint_type,
       c.table_name,
       c.index_name,
       c.status
FROM user_constraints c
WHERE c.index_name = 'IDX_ORDERS_01';
check-index-columns.sql
SELECT index_name,
       column_position,
       column_name,
       descend
FROM user_ind_columns
WHERE index_name = 'IDX_ORDERS_01'
ORDER BY column_position;

制約全体の確認方法は Oracle制約の記事、一意制約違反との関係は ORA-00001の記事 も参考になります。

パーティションインデックスを確認する

パーティション表では、インデックス全体のSTATUSだけでは分からないことがあります。インデックスパーティションやサブパーティションの状態を確認します。

check-unusable-index-partitions.sql
SELECT index_name,
       partition_name,
       status
FROM user_ind_partitions
WHERE status = 'UNUSABLE'
ORDER BY index_name, partition_position;
check-unusable-index-subpartitions.sql
SELECT index_name,
       partition_name,
       subpartition_name,
       status
FROM user_ind_subpartitions
WHERE status = 'UNUSABLE'
ORDER BY index_name, partition_name, subpartition_name;

パーティション操作では、ローカルインデックスとグローバルインデックスで影響が変わります。エラーが出た表にパーティション操作をした直後なら、どのインデックスがどの単位でUNUSABLEになっているかを先に確認します。

通常インデックスをREBUILDする

通常インデックスがUNUSABLEなら、ALTER INDEX ... REBUILD で再構築します。本番では実行時間、TEMP使用量、表領域、ロック、ONLINE可否を確認してから実行します。

rebuild-index.sql
ALTER INDEX idx_orders_01 REBUILD;

-- 表領域を指定する例
ALTER INDEX idx_orders_01 REBUILD TABLESPACE users;

大きなインデックスのREBUILDではTEMP表領域を使うことがあります。TEMP不足で失敗する場合は ORA-01652の記事 も参考になります。表領域の空きは 表領域の記事、容量不足の緊急対応は 容量不足の記事 も確認してください。

パーティション単位でREBUILDする

インデックスパーティションだけがUNUSABLEなら、全体ではなく対象パーティションだけREBUILDします。不要に全体REBUILDすると時間と負荷が大きくなります。

rebuild-index-partition.sql
ALTER INDEX idx_orders_g01
REBUILD PARTITION p202605;

-- サブパーティションの場合
ALTER INDEX idx_orders_g01
REBUILD SUBPARTITION sp202605_01;

対象がローカルインデックスなのかグローバルインデックスなのかで、再構築対象と影響範囲が変わります。パーティション操作後に発生した場合は、直前に実行した ALTER TABLE ... MOVE PARTITIONTRUNCATE PARTITIONEXCHANGE PARTITION などを確認します。

発生しやすい操作

ORA-01502は、何かのDDLや大量ロードの後に出ることが多いです。直前の作業履歴を確認すると原因に近づきやすくなります。

ALTER TABLE MOVE

表をMOVEすると、関連インデックスがUNUSABLEになることがあります。MOVE後にインデックスREBUILDが必要です。

パーティション操作

DROP/TRUNCATE/MOVE/EXCHANGE PARTITION後に、グローバルインデックスがUNUSABLEになることがあります。

SQL*Loaderのダイレクトパス

大量ロードやダイレクトパス処理でインデックスがUNUSABLEになることがあります。

インデックス作成・再構築失敗

REBUILD中に容量不足や中断があると、UNUSABLE状態が残ることがあります。

NOLOGGING/大量更新

運用手順によっては、性能優先の処理後にインデックス状態確認が必要です。

ALTER TABLE の各操作と注意点は ALTER TABLEの記事 も参考になります。

UNUSABLEのままにしてよいか

基本的に、業務で使うインデックスをUNUSABLEのまま放置するのは避けます。SQLが遅くなるだけでなく、制約を支えるインデックスではDMLが失敗する可能性があります。

一時的に無効化しただけ

ロード作業などで意図的にUNUSABLEにした場合でも、作業後にREBUILDする手順を明確にします。

不要なインデックス

本当に不要なら、REBUILDではなく削除を検討します。ただし影響調査が必要です。

制約を支えるインデックス

主キーや一意制約に関係する場合は、業務影響が大きいため優先して復旧します。

大きな本番インデックス

ONLINE、PARALLEL、表領域、TEMP、実行時間、負荷を確認して計画的にREBUILDします。

INSERT、UPDATE、DELETE、MERGEなどの更新処理でORA-01502が出る場合は、対象表の制約やインデックス状態を先に確認します。DML全体の基本は INSERT・UPDATE・DELETEの記事、MERGE処理は MERGE文の記事 も参考になります。

REBUILD時の注意点

REBUILDは便利ですが、無条件に実行すると本番負荷や容量不足を招くことがあります。実行前に対象サイズ、表領域空き、TEMP空き、ロック影響、ONLINE可否を確認します。

check-index-size.sql
SELECT segment_name,
       segment_type,
       ROUND(bytes / 1024 / 1024) AS size_mb
FROM user_segments
WHERE segment_name = 'IDX_ORDERS_01';
rebuild-index-online.sql
ALTER INDEX idx_orders_01 REBUILD ONLINE;

-- 実行後に状態確認
SELECT index_name, status
FROM user_indexes
WHERE index_name = 'IDX_ORDERS_01';

ONLINE が使えるかどうかはエディション、バージョン、インデックス種別、操作内容に依存します。本番では事前検証し、必要に応じてメンテナンス時間帯で実行してください。

セッションやロックを確認する

REBUILD中やDDL実行中に待ちが発生することがあります。長時間止まっているように見える場合は、セッションやロックを確認します。

check-ddl-session.sql
SELECT sid,
       serial#,
       username,
       status,
       event,
       wait_class,
       seconds_in_wait,
       sql_id,
       module
FROM v$session
WHERE username IS NOT NULL
ORDER BY seconds_in_wait DESC;

セッションやロックの見方は セッション確認の記事 を参照してください。

対応手順まとめ

  1. エラーに出たインデックス名または対象表を確認する
  2. USER_INDEXES / DBA_INDEXESUNUSABLE を確認する
  3. パーティション表なら USER_IND_PARTITIONS も確認する
  4. 通常インデックスなら ALTER INDEX ... REBUILD を検討する
  5. パーティションインデックスなら対象パーティションだけREBUILDする
  6. REBUILD前に表領域、TEMP、実行時間、ONLINE可否を確認する
  7. 直前の ALTER TABLE MOVE やパーティション操作の履歴を確認する
  8. 復旧後にインデックス状態と業務SQLの動作を確認する

ORA-01502は、インデックスをREBUILDすれば解消することが多いエラーです。ただし、本番では対象が通常インデックスかパーティションインデックスか、制約を支えているか、REBUILDに必要な容量があるかを確認してから実行します。直前のDDLや大量ロードの手順も見直し、作業後にインデックス状態を確認する運用にしておくと再発を防ぎやすくなります。

よくある質問

ORA-01502はALTER INDEX REBUILDで直りますか?

通常インデックスなら直ることが多いです。ただし、パーティションインデックスでは対象パーティション単位のREBUILDが必要なことがあります。

UNUSABLEインデックスを放置するとどうなりますか?

SQLが遅くなるだけでなく、制約に関係するインデックスではINSERT/UPDATEが失敗することがあります。不要でない限り復旧対象として扱います。

REBUILDでTEMP不足になります

インデックスREBUILDはTEMPや表領域を使うことがあります。空き容量を確認し、必要なら時間帯、並列度、表領域、TEMPFILEを見直します。

ALTER TABLE MOVE後に出ました

MOVE後に関連インデックスがUNUSABLEになることがあります。MOVEとインデックスREBUILDをセットの作業手順として管理します。

参考