【Oracle】NOLOGGING完全ガイド|REDO 生成量の削減・FORCE LOGGING との関係・バッチ処理高速化まで解説

Oracle の通常の DML は、障害回復のために変更内容を REDO ログに記録します。NOLOGGING を指定すると、特定の操作において REDO ログへの書き込みを最小限に抑え、大量データのロードや索引の再作成を数倍高速化できます。

ただし NOLOGGING を使った操作後にメディア障害(ディスク障害)が発生すると、NOLOGGING で書き込んだデータは REDO から復元できません。適切なバックアップ戦略と組み合わせて使うことが重要です。

この記事でわかること

  • NOLOGGING でどの操作が高速化されるか(対応操作と非対応操作)
  • テーブル・インデックス・パーティションへの NOLOGGING の設定方法
  • ダイレクト・パス INSERT(APPEND ヒント)との組み合わせ
  • FORCE LOGGING でデータベース全体の NOLOGGING を無効化する方法
  • NOLOGGING 使用後のメディア障害リスクと対処法
  • ALL_TABLES / ALL_INDEXES の LOGGING 列での設定確認
スポンサーリンク

NOLOGGING の仕組みと REDO ログとの関係

Oracle はすべての変更操作を REDO ログに記録します。これが Instance Recovery(インスタンス障害後の自動回復)の基盤です。NOLOGGING は REDO への書き込みを最小化することで I/O を削減し、ログバッファの競合を緩和します。

操作 NOLOGGING 対応 効果
CREATE TABLE AS SELECT (CTAS) 対応 データブロックの REDO を抑制
CREATE INDEX(全体再作成) 対応 インデックスブロックの REDO を抑制
INSERT /*+ APPEND */ (ダイレクト・パス INSERT) 対応 データブロックの REDO を抑制
ALTER TABLE MOVE 対応 移動先ブロックの REDO を抑制
ALTER INDEX REBUILD 対応 インデックスブロックの REDO を抑制
通常の INSERT / UPDATE / DELETE 非対応 NOLOGGING 設定に関わらず REDO に記録される
SELECT 非対応(無意味)
NOLOGGING は「ログなし」ではなく「最小ログ」
NOLOGGING でも操作自体のメタデータ(「このブロックは NOLOGGING で更新された」という記録)は REDO に書かれます。完全にログが生成されないわけではなく、ブロックの変更前後の差分(REDO データ)を抑制するものです。

テーブルとインデックスへの NOLOGGING 設定

CREATE / ALTER TABLE・INDEX での NOLOGGING 設定
-- CREATE TABLE に NOLOGGING を付ける
CREATE TABLE sales_archive (
    sale_id     NUMBER,
    sale_date   DATE,
    amount      NUMBER
) NOLOGGING;   -- ← テーブル属性として NOLOGGING を設定

-- 既存テーブルを NOLOGGING に変更する
ALTER TABLE sales_archive NOLOGGING;

-- LOGGING に戻す
ALTER TABLE sales_archive LOGGING;

-- CREATE TABLE AS SELECT (CTAS) + NOLOGGING: 非常に速い
CREATE TABLE new_sales NOLOGGING AS
SELECT * FROM sales WHERE sale_date >= DATE '2024-01-01';
-- LOGGING の場合より大幅に REDO 書き込みが減る(ケースによっては数倍高速)

-- CREATE INDEX + NOLOGGING
CREATE INDEX idx_sales_date ON sales(sale_date) NOLOGGING;

-- 既存インデックスを NOLOGGING で再作成する(REBUILD)
ALTER INDEX idx_sales_date REBUILD NOLOGGING;

-- インデックスを REBUILD 後に LOGGING に戻す
ALTER INDEX idx_sales_date LOGGING;

-- パーティション単位での NOLOGGING 設定
CREATE TABLE sales_partitioned (
    sale_id   NUMBER,
    sale_date DATE,
    amount    NUMBER
)
PARTITION BY RANGE (sale_date) (
    PARTITION p2023 VALUES LESS THAN (DATE '2024-01-01') NOLOGGING,
    PARTITION p2024 VALUES LESS THAN (DATE '2025-01-01') LOGGING
);
-- アーカイブパーティションは NOLOGGING、最新データは LOGGING と使い分けられる

ダイレクト・パス INSERT(APPEND ヒント)との組み合わせ

テーブルが NOLOGGING の場合でも、通常の INSERT は REDO に記録されます。APPEND(または APPEND_VALUES)ヒントによるダイレクト・パス INSERT を組み合わせることで、INSERT も REDO 最小化の恩恵を受けられます。

NOLOGGING テーブルへのダイレクト・パス INSERT
-- NOLOGGING テーブルへの通常 INSERT(REDO に記録される)
INSERT INTO sales_archive SELECT * FROM sales_staging;
COMMIT;
-- NOLOGGING 属性があっても、通常 INSERT は REDO が生成される

-- APPEND ヒント + NOLOGGING テーブル: REDO を最小化できる
INSERT /*+ APPEND */ INTO sales_archive
SELECT * FROM sales_staging;
COMMIT;
-- ダイレクト・パス INSERT では NOLOGGING テーブルへの挿入で REDO を抑制できる

-- APPEND で HIGH WATER MARK 以降に書き込む(既存データはスキャン不要)
-- → ただし、COMMIT するまでテーブルはロックされる(他セッションからの INSERT 不可)

-- ダイレクト・パス INSERT + PARALLEL でさらに高速化
INSERT /*+ APPEND PARALLEL(4) */ INTO sales_archive
SELECT * FROM sales_staging;
COMMIT;

-- REDO 生成量を確認する(V$MYSTAT で統計値を比較)
SELECT s.name, ss.value
FROM   V$MYSTAT ss, V$STATNAME s
WHERE  ss.statistic# = s.statistic#
  AND  s.name IN ('redo size', 'redo entries')
ORDER  BY s.name;
-- REDO サイズがどれだけ減ったか確認できる

FORCE LOGGING でデータベース全体の NOLOGGING を無効化する

FORCE LOGGING はデータベース全体(または PDB)で NOLOGGING を無効化する設定です。Oracle Data Guard(スタンバイへのログ送信)やGoldenGate(CDC ツール)を使っている環境では、NOLOGGING でデータが書き込まれるとスタンバイに反映されないためFORCE LOGGING が必須です。

FORCE LOGGING の確認と設定
-- データベースが FORCE LOGGING モードかどうかを確認する
SELECT name, force_logging FROM V$DATABASE;
-- force_logging = YES: NOLOGGING 指定をすべて無視してフル REDO を生成する

-- FORCE LOGGING を有効化する(DBA 権限が必要)
ALTER DATABASE FORCE LOGGING;

-- FORCE LOGGING を無効化する
ALTER DATABASE NO FORCE LOGGING;

-- Pluggable Database (PDB) 単位での FORCE LOGGING(Oracle 12c マルチテナント環境)
ALTER PLUGGABLE DATABASE FORCE LOGGING;
ALTER PLUGGABLE DATABASE NO FORCE LOGGING;

-- NOLOGGING ブロックが存在するかどうかを確認する
-- NOLOGGING で書き込まれたブロックは V$DATAFILE の UNRECOVERABLE_CHANGE# > 0 になる
SELECT file#, name, unrecoverable_change#, unrecoverable_time
FROM   V$DATAFILE
WHERE  unrecoverable_change# > 0;
-- 0 以外の行がある = このデータファイルに NOLOGGING 書き込みが存在する
-- → 障害時に Recovery が必要かどうかの判断に使う

NOLOGGING のリスクとバックアップ戦略

NOLOGGING 使用後のメディア障害リスク
NOLOGGING で書き込んだデータはアーカイブ REDO ログから復元できません。NOLOGGING 操作後にメディア障害が発生した場合、その操作で書き込んだデータは「ORA-26040: Data block was loaded using the NOLOGGING option」エラーが返り、ブロックが復元不可能な状態になります。NOLOGGING 操作が完了したら直ちにバックアップ(RMAN など)を取得してください。
NOLOGGING 操作後のバックアップと確認
-- 安全な NOLOGGING 運用手順:
-- 1. NOLOGGING 操作前にバックアップを確認する
-- 2. NOLOGGING 操作を実行する
-- 3. 操作後に RMAN バックアップを取得する(完全バックアップ または 増分バックアップ)

-- RMAN での NOLOGGING ブロックを含むデータファイルのバックアップ
-- RMAN> BACKUP DATAFILE 5, 6;  -- NOLOGGING 書き込みがあったデータファイルをバックアップ

-- テーブル・インデックスの LOGGING 設定を確認する
SELECT table_name, logging
FROM   USER_TABLES
WHERE  logging = 'NO'   -- NOLOGGING テーブルを一覧する
ORDER  BY table_name;

SELECT index_name, logging
FROM   USER_INDEXES
WHERE  logging = 'NO'   -- NOLOGGING インデックスを一覧する
ORDER  BY index_name;

-- 本番環境での一般的な使い方:
-- ・バッチ処理の中間テーブル(GTT や一時作業テーブル)→ NOLOGGING で問題なし
-- ・アーカイブ用の書き込み専用テーブル → バックアップ後は NOLOGGING で高速ロード
-- ・Data Guard がある場合 → FORCE LOGGING を設定して NOLOGGING を禁止する
-- ・インデックスの定期 REBUILD → NOLOGGING で時間を短縮し、直後にバックアップ

まとめ

  • NOLOGGING の効果:CREATE TABLE AS SELECT・CREATE INDEX・ダイレクト・パス INSERT などの「バルク操作」でブロックへの REDO 書き込みを最小化する。通常の INSERT/UPDATE/DELETE は NOLOGGING 設定に関わらず REDO に記録される
  • APPEND ヒントとの組み合わせ:NOLOGGING テーブルにダイレクト・パス INSERT することで、大量データの挿入も REDO を抑制できる
  • FORCE LOGGING:Data Guard / GoldenGate 環境では必須。ALTER DATABASE FORCE LOGGING でデータベース全体の NOLOGGING を無効化する
  • リスク管理:NOLOGGING で書いたデータはアーカイブ REDO から復元不可。操作後は必ず RMAN バックアップを取る
  • 設定確認:USER_TABLES.LOGGING / USER_INDEXES.LOGGING で YES/NO を確認する。V$DATAFILE.UNRECOVERABLE_CHANGE# でNOLOGGING ブロックの有無を確認する

REDO ログの管理(サイズ変更・ログスイッチの確認)については オンライン REDO ログ完全ガイドを参照してください。ダイレクト・パス INSERT の詳細は ダイレクト・パス INSERT 完全ガイドも参照してください。