◀ 2.

Oracle 19cの索引再構築|REBUILDの判断・ONLINEと制約

▶

Oracle 19cの索引再構築を、対象確認・必要性の判断・実行影響に分けて説明します。SQLは新しいSELECT例を含めOracle未実行です。実機のロック時間・性能・復旧を検証した記事ではありません。

Oracle 19cの索引再構築について対象確認、必要性、実行条件を分ける判断の模式図。SQL実測結果ではありません
索引の対象と状態を確認し、変更しない選択も含めて必要性を判断する模式図です。ONLINEは無停止の保証ではなく、この図はSQL実測・性能改善・復旧成功の証明ではありません。
この記事の要点
  • Oracle の索引再構築は ALTER INDEX index_name REBUILD が基本。必要性と対象種別を先に確認する
  • オンライン再構築: Oracle 19cの ALTER INDEX ... REBUILD ONLINE は再構築中のDMLを許可する指定。対象制限と競合・負荷があり、無停止や固定時間を保証しない
  • 別表領域への移動は REBUILD TABLESPACE new_ts。宛先の権限・quota・容量を確認する
  • 構造検証の ANALYZE INDEX ... VALIDATE STRUCTURE は既定OFFLINEでDMLを制限する。INDEX_STATS は最後の構造検証の結果でoptimizer統計とは別。無作用の診断として実行しない
  • MySQLの OPTIMIZE TABLE、PostgreSQLの REINDEX 等は製品別の操作であり、対象範囲・ロック・構文は同一ではない

索引の再作成 (REBUILD) とは

大量更新・削除等で索引の領域効率が変化する場合があります。ただし空き領域の存在だけでは検索性能の劣化や再構築による改善を断定できません。ALTER INDEX ... REBUILD は索引を再構築し、領域や格納属性の変更にも用います。既存の索引を入力にできる利点はありますが、すべての索引形態を同じ方式では扱えません。

対象確認から判断まで

  1. 接続先DB・所有schema・索引名・対象表・索引種別・制約を照合します。名前からlocal/globalやpartition名を推測せず、索引本体とpartition/subpartitionの状態を別々に確認します。
  2. 困っているSQL、実行条件・結果・実行計画とI/O・実行時間、既存の統計取得日時を確認します。古い統計値は現在の全体像ではありません。ここではANALYZEや統計収集を診断手順に追加しません。
  3. 空きの索引内再利用か表領域への返却か、目的を明確にします。変更しない・COALESCE・必要なREBUILDを費用対効果で比較し、固定閾値だけで自動実行しません。
  4. 実行を選ぶ場合は導入版・edition・利用権、権限、quota、追加領域・一時領域、同時処理、実行枠と復旧方針を確認します。DDLの暗黙COMMITを考慮し、先行DMLや途中までのDDLを一括ROLLBACKできるとは扱いません。
  5. 実行後は同じ対象の状態・制約・格納属性・統計・計画と同じSQLの結果・実測を比較します。エラー時は状態確認を先にし、制約DROP・表MOVE・PURGEを自動選択しません。

次はログインユーザーが所有する索引のSELECT例です。名前は実際の辞書値に置き換え、引用識別子の大文字小文字も合わせます。USER_*の可視範囲に限られ、0件は他schemaの不存在証明ではありません。STATUSがVALIDでも再構築の必要性や全partitionの健全性は証明できません。統計列の値やLAST_ANALYZEDは既存情報の参照であり、新しい統計収集ではありません。新SQLもOracle未実行です。

-- Oracle 19c: current user's own indexes only. NOT run on Oracle.
-- Replace IDX_USERS_EMAIL with the exact dictionary name.
SELECT index_name, table_name, index_type, uniqueness, partitioned,
       status, tablespace_name, last_analyzed
FROM user_indexes
WHERE index_name = 'IDX_USERS_EMAIL'
ORDER BY index_name;

SELECT index_name, partition_name, status, tablespace_name
FROM user_ind_partitions
WHERE index_name = 'IDX_USERS_EMAIL'
ORDER BY index_name, partition_position;

SELECT index_name, partition_name, subpartition_name, status, tablespace_name
FROM user_ind_subpartitions
WHERE index_name = 'IDX_USERS_EMAIL'
ORDER BY index_name, partition_name, subpartition_position;

SELECT constraint_name, constraint_type, table_name, status,
       deferrable, deferred, validated, index_owner, index_name
FROM user_constraints
WHERE index_owner = USER AND index_name = 'IDX_USERS_EMAIL'
ORDER BY constraint_name;

基本構文

以下は旧掲載の独立した変更DDLの構文比較です。一括実行用ではありません。ONLINE/COMPRESS/PARALLEL/NOLOGGINGは無条件の推奨ではなく対象制限があります。「11g以降、推奨」「並列度を指定して高速化」「ログ無しで高速化」は保証ではありません。PARALLEL 4は後続操作の並列度属性にも影響します。NOLOGGINGでも最小限のredoがあり、FORCE LOGGINGで扱いが変わり、事前backupからのmedia recoveryに制限があるためstandby/復旧方針を確認します。TABLESPACE省略時は従来の表領域を使います。Oracle未実行です。

-- 最もシンプルな再構築
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でも無ロック・無待機ではない削除に成功すればその索引は利用不可。作成完了までの業務影響と競合を確認
ディスク使用量旧索引に加え再構築先・一時領域等を見積もる。固定2倍ではない削除後の領域再利用・作成先・一時領域等を別途見積もる。新領域のみとは限らない
主キー / 一意制約制約定義を削除する操作ではない。実行制限は別有効PK/UNIQUE関連索引の単独DROPは不可。制約も自動削除されるという意味ではない
ヒント / 統計情報同名維持はhintの適用・同じ計画や性能の保証ではない。操作後の統計と計画を確認再作成した定義・統計とhintの適用を再確認。全hint/統計の一律リセットとは扱わない
処理速度既存索引を入力にできる利点があるが、所要時間と検索改善は要比較再作成には元表の索引対象データを読む。方式・対象・負荷次第で一律の速度比較はしない

再構築が必要と判断した場合も、対象制限・権限・領域・復旧方針・業務影響を比較してONLINEを含む方式を選びます。列順・タイプ変更と、同じ定義の再構築は目的が異なります。DROPを通すための制約解除は案内しません。

断片化の確認

旧例は読取SELECTだけではありません。先頭のANALYZE INDEX ... VALIDATE STRUCTUREは既定OFFLINEで検証中のINSERT/UPDATE/DELETEを許しません。問合せは可能ですが無作用の診断ではありません。INDEX_STATSは最後の構造検証の結果で、全索引の現在値やoptimizer統計ではありません。ONLINE検証は検証量が減り統計を収集しないため、付加するだけでは同じ測定になりません。「HEIGHT 4以上」「PCT_USED 50%未満」は普遍的基準ではありません。後半DBMS_SPACE.SPACE_USAGEのこのoverloadはASSM表領域のHWM以下のdata blockが対象で、header/bitmap/extent mapを含まず、確実な返却量ではありません。partitionでは指定を別途確認します。ローカル変数の表示・保存は省略されており、実行すれば画面に値が出る例ではありません。Oracle未実行です。

-- インデックスの構造を解析
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;
/

再構築が必要な目安

見出しの「目安」は自動実行条件ではありません。次の値は対象自身の推移と実際のSQL・目的を合わせて判断します。

  • PCT_USED: 領域使用率の観測。50%未満だけで実施を決めず、索引内での空き再利用と返却目的を確認します。
  • DEL_LF_ROWS / LF_ROWS: 削除済みリーフ行の比率。20%超だけで過多と断定せず、LF_ROWSが0またはNULLなら比率判定しません。
  • HEIGHT: B-Treeの高さ。4以上だけで異常・非効率と決めず、対象規模・利用SQL・I/O/実行時間を照合します。
  • 大量DELETE/UPDATEだけを理由に月次・四半期REBUILDを設定しません。変更しない選択、COALESCE、必要な再構築を費用と効果で比較します。

ONLINE オプションの注意

Oracle 19cのONLINEは再構築中のDMLを許可する指定で、無ロック・無待機・無影響ではありません。parallel DMLはサポートされず、bitmap join索引・cluster索引やdeferrable unique制約を強制する索引には制限があります。導入版・edition・利用権も別途確認します。

  • 再構築用の追加領域と一時領域等を見積もります。旧索引のちょうど2倍という固定容量ではありません。
  • 同時DMLを許可する指定と、その更新を整合させる実処理・追加負荷を区別します。旧説明の「ジャーナル表に記録して最後に適用」を全対象の検証済み内部手順として保証しません。
  • ロック取得・競合の可能性を確認し、完了や待機を「通常数秒」と見積もりません。
  • 大量更新と競合する実行枠の負荷を評価します。閑散期でも無停止・成功の保証にはなりません。

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

索引の再構築と表partitionの移動は別操作です。MOVE PARTITIONは表データのsegmentを移し、local索引の対応partitionをUNUSABLEにする場合があります。UPDATE GLOBAL INDEXESは利用可能なglobal索引を保守する指定で、既存UNUSABLE global索引の汎用復旧ではありません。local/global・索引本体・各partitionの既存状態と影響を先に確認します。

旧例の先頭は索引側のpartition名を確認し、表partition名から推定しません。「全パーティション(一括)」に続くALTER INDEX idx_orders_local REBUILDはパーティション索引全体の再構築には使えません。索引partition/subpartitionごとに対象を確認し、複合partition表のlocal索引にはSUBPARTITION指定が必要です。末尾ALTER TABLE ... MOVE PARTITION ... UPDATE GLOBAL INDEXESは表データを移動するDDLで、既存UNUSABLE global索引の一般的な復旧手順ではありません。索引確認のために実行しないでください。Oracle未実行です。

-- ローカルパーティション索引の特定パーティションのみ
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;

運用バッチ例

次は非推奨の旧自動保守例を比較教材として保持したものです。実用的な判断は「対象確認から判断まで」を参照してください。

以下は旧掲載の自動保守例であり実行を推奨しません。APPのVALID索引を広く対象にし、ANALYZEと条件付きREBUILDを実行します。断片化率を事前に抽出しておらず、VALIDは実行の安全性・必要性・改善の証明ではありません。ANALYZEの既定OFFLINEは検証中のDMLを許さず、PCT_USED 50未満・HEIGHT 4以上だけで利益を判断できません。ONLINE非対応の対象、引用識別子・長さ、権限・容量・競合や途中失敗も未対処です。DDLには暗黙COMMITがあり、途中までのDDLや先行DMLはブロック全体のROLLBACKでは取り消せません。このコードをジョブや定期保守へ登録しないでください。Oracle未実行です。

-- 断片化率が高い索引を自動抽出して再構築する 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 の同等コマンド

「同等」は共通の実行手順という意味ではありません。既存の製品別比較を保持していますが、本記事の再確認対象はOracle 19cのみです。他製品の版・edition・構文完全形・制限は別途確認してください。PGの省略形などを実行可能な完成文としてコピーしないでください。

DBコマンド備考
OracleALTER INDEX ... REBUILD ONLINE19cで対象制限・権限・利用条件を確認。ONLINEは無停止保証ではない
MySQL (InnoDB)OPTIMIZE TABLE tbl; / ALTER TABLE tbl ENGINE=InnoDB;表単位の操作として索引単体の操作と区別。対象版の動作・制限を別途確認
PostgreSQLREINDEX INDEX idx; / REINDEX CONCURRENTLYCONCURRENTLY等の完全構文・対象版・制限を別途確認。無停止の意味ではない
SQL ServerALTER INDEX idx ON tbl REBUILD WITH (ONLINE = ON)版・edition・対象・ONLINEの制限を別途確認
DB2REORG INDEXES ALL FOR TABLE tbl製品版・対象範囲・オプションを別途確認

FAQ

Q: REBUILD と COALESCE の違いは?
A: COALESCE は同じbranch内のleaf blockを結合して索引内の再利用を促すオンライン操作です。REBUILD は新しいtreeを作り、必要なら高さや表領域等を変更できます。COALESCEも定期実施の義務ではなく、処理の費用・再利用/領域返却の目的と効果を比較します。表領域やOSへ同じ量を返す操作とは扱いません。

Q: 再構築中にエラーで止まったらどうなる?
A: 検索継続や索引の利用可否は、実際のエラー・索引/partitionの状態・進行中処理と依存を確認するまで保証できません。DBA_SEGMENTS で見えたsegmentを残骸と決めてPURGE/DROPしないでください。PURGE はrecycle binの対象等を不可逆に除去する操作で、任意の残存segmentの掃除コマンドではありません。通常ROLLBACKやrecycle binからの復旧はできません。対象と原因に応じて管理者が復旧方針を判断します。

Q: 主キー索引を REBUILD すると制約に影響する?
A: REBUILDは主キー/一意制約の定義を削除する操作ではありません。ただし索引形態・ONLINE等の制限と実行影響は別です。有効なPRIMARY KEY/UNIQUE制約に関連する索引だけを単独DROPすることはできません。「索引DROPで制約も消える」とは扱わず、制約定義・状態と使用索引を確認します。DROPを成功させるために制約を解除する手順にはしません。

公式資料と確認範囲

2026-10-27にOracle 19c公式一次資料を再確認しました。構文・制限の文書照合であり、Oracle実機・記事SQL・ロック・性能・復旧・利用権の検証ではありません。索引関連から作成・削除等の別操作も確認できます。

子ページ

子ページはありません

同階層のページ
  1. 索引の作成 (索引関連 SQL)
  2. 索引の再作成
  3. 索引の削除(DROP INDEX)

最近更新/作成されたページ