この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:5
ページ更新者:guest
更新日時:2026-06-11 07:29:05

タイトル: 索引の再作成
SEOタイトル: Oracle 索引 (Index) の再作成完全ガイド

この記事の要点
  • Oracle の索引再構築ALTER INDEX index_name REBUILD が基本
  • オンライン再構築: ALTER INDEX ... REBUILD ONLINE で DML を止めずに実行可能 (Oracle 11g+)
  • 別表領域への移動を兼ねるなら REBUILD TABLESPACE new_ts
  • 断片化の確認は ANALYZE INDEX ... VALIDATE STRUCTUREINDEX_STATS ビューを参照
  • MySQL は OPTIMIZE TABLE、PostgreSQL は REINDEX が同等処理

索引の再作成 (REBUILD) とは

Oracle のインデックスは、大量の更新・削除が繰り返されるとリーフブロックに空き領域 (フラグメンテーション) が発生し、検索性能が劣化します。ALTER INDEX ... REBUILD は既存インデックスから新しい B-Tree を構築し直し、断片化を解消するためのコマンドです。

基本構文

-- 最もシンプルな再構築
ALTER INDEX idx_users_email REBUILD;

-- オンライン再構築 (Oracle 11g以降、推奨)
ALTER INDEX idx_users_email REBUILD ONLINE;

-- 別の表領域に移動しつつ再構築
ALTER INDEX idx_users_email REBUILD TABLESPACE users_idx_ts;

-- 並列度を指定して高速化
ALTER INDEX idx_users_email REBUILD PARALLEL 4;

-- 圧縮しつつ再構築
ALTER INDEX idx_users_email REBUILD COMPRESS;

-- ログ無しで高速化 (リカバリ不能になるので注意)
ALTER INDEX idx_users_email REBUILD NOLOGGING;

再構築 (REBUILD) vs 再作成 (DROP + CREATE)

項目REBUILDDROP + CREATE
排他ロックONLINE 指定で回避可能DROP の瞬間に完全消失
ディスク使用量旧 + 新で一時的に 2 倍必要新領域のみ
主キー / 一意制約制約はそのまま維持制約も削除される → 再定義必要
ヒント / 統計情報引き継がれるリセットされる
処理速度既存索引をソート済み入力として高速テーブル全走査が必要

原則として REBUILD ONLINE を使い、DROP + CREATE は索引の構成 (列順・タイプ) を変更したい場合のみに留めます。

断片化の確認

-- インデックスの構造を解析
ANALYZE INDEX idx_users_email VALIDATE STRUCTURE;

-- 結果は INDEX_STATS ビューで確認 (セッション内のみ有効)
SELECT
    name,
    height,                    -- B-Tree の高さ (4以上で深すぎ)
    blocks,                    -- 確保ブロック数
    lf_rows,                   -- リーフ行数
    lf_blks,                   -- リーフブロック数
    del_lf_rows,               -- 削除済みリーフ行
    del_lf_rows_len,           -- 削除済み行のサイズ
    used_space,
    pct_used                   -- 使用率 (50%未満で再構築検討)
FROM index_stats;

-- DBMS_SPACE.SPACE_USAGE で詳細な空き状況を取得
DECLARE
    unformatted_blocks NUMBER;
    unformatted_bytes  NUMBER;
    fs1_blocks  NUMBER; fs1_bytes  NUMBER;
    fs2_blocks  NUMBER; fs2_bytes  NUMBER;
    fs3_blocks  NUMBER; fs3_bytes  NUMBER;
    fs4_blocks  NUMBER; fs4_bytes  NUMBER;
    full_blocks NUMBER; full_bytes NUMBER;
BEGIN
    DBMS_SPACE.SPACE_USAGE(
        segment_owner      => 'APP',
        segment_name       => 'IDX_USERS_EMAIL',
        segment_type       => 'INDEX',
        unformatted_blocks => unformatted_blocks,
        unformatted_bytes  => unformatted_bytes,
        fs1_blocks => fs1_blocks, fs1_bytes => fs1_bytes,
        fs2_blocks => fs2_blocks, fs2_bytes => fs2_bytes,
        fs3_blocks => fs3_blocks, fs3_bytes => fs3_bytes,
        fs4_blocks => fs4_blocks, fs4_bytes => fs4_bytes,
        full_blocks => full_blocks, full_bytes => full_bytes
    );
END;
/

再構築が必要な目安

  • PCT_USED < 50% → 断片化が進行、再構築を検討
  • DEL_LF_ROWS / LF_ROWS > 20% → 削除済み行が多すぎ
  • HEIGHT >= 4 → B-Tree が深くなりすぎ、行数のわりに非効率
  • 定期的に大量 DELETE / UPDATE するテーブル → 月次・四半期で再構築

ONLINE オプションの注意

Oracle 11g 以降では REBUILD ONLINE により DML をブロックせず再構築できますが、内部的には以下が起こります:

  • 新しい索引セグメントが旧索引と並行して構築される (ディスク 2 倍必要)
  • 再構築中に発生した DML は ジャーナル表に記録され、最後に適用
  • 適用フェーズで一瞬だけ排他ロックが発生 (通常は数秒)
  • 大量更新の最中はジャーナルが肥大化 → 業務閑散期に実施推奨

パーティション索引の再構築

-- ローカルパーティション索引の特定パーティションのみ
ALTER INDEX idx_orders_local REBUILD PARTITION p_2025_q1 ONLINE;

-- 全パーティション (一括)
ALTER INDEX idx_orders_local REBUILD;

-- グローバル索引で UNUSABLE 状態を解消
ALTER TABLE orders MOVE PARTITION p_2024_q4 UPDATE GLOBAL INDEXES;

運用バッチ例

-- 断片化率が高い索引を自動抽出して再構築する PL/SQL
DECLARE
    v_sql VARCHAR2(500);
BEGIN
    FOR rec IN (
        SELECT i.owner, i.index_name
        FROM   dba_indexes i
        WHERE  i.owner = 'APP'
        AND    i.status = 'VALID'
    ) LOOP
        v_sql := 'ANALYZE INDEX ' || rec.owner || '.' || rec.index_name
                 || ' VALIDATE STRUCTURE';
        EXECUTE IMMEDIATE v_sql;

        FOR s IN (SELECT pct_used, height FROM index_stats) LOOP
            IF s.pct_used < 50 OR s.height >= 4 THEN
                v_sql := 'ALTER INDEX ' || rec.owner || '.' || rec.index_name
                         || ' REBUILD ONLINE';
                DBMS_OUTPUT.PUT_LINE('Rebuilding: ' || rec.index_name);
                EXECUTE IMMEDIATE v_sql;
            END IF;
        END LOOP;
    END LOOP;
END;
/

他 DBMS の同等コマンド

DBコマンド備考
OracleALTER INDEX ... REBUILD ONLINE11g+ でオンライン可
MySQL (InnoDB)OPTIMIZE TABLE tbl; / ALTER TABLE tbl ENGINE=InnoDB;テーブル全体を再構築
PostgreSQLREINDEX INDEX idx; / REINDEX CONCURRENTLY12+ でオンライン化対応
SQL ServerALTER INDEX idx ON tbl REBUILD WITH (ONLINE = ON)Enterprise Edition で ONLINE 可
DB2REORG INDEXES ALL FOR TABLE tbl

FAQ

Q: REBUILD と COALESCE の違いは?
A: COALESCE は隣接するリーフブロックの空き領域だけを結合 (オンライン・低負荷)、REBUILD は索引全体を再構築 (リソース要求大・ディスク 2 倍)。日常メンテは COALESCE、深刻な断片化は REBUILD。

Q: 再構築中にエラーで止まったらどうなる?
A: 旧索引はそのまま残るので検索は継続できます。新索引のセグメントが残骸として残る場合があるので DBA_SEGMENTS で確認し PURGE してください。

Q: 主キー索引を REBUILD すると制約に影響する?
A: 影響なし。主キー・一意制約は索引に紐付くが、REBUILD では制約自体は維持されます。DROP すると制約も消えます。