【Oracle】PL/SQL ネイティブコンパイル完全ガイド|NATIVE モードで演算処理を高速化・コンパイルモードの変更まで解説

PL/SQL は通常、中間コード(バイトコード)にコンパイルされて Oracle 内部インタープリタで実行されます(INTERPRETED モード)。ネイティブコンパイル(NATIVE モード)を有効にすると、PL/SQL コードがオペレーティングシステムのネイティブ機械語コードにコンパイルされます。

ネイティブコンパイルは特に数値演算・文字列処理・複雑なロジックのループを含む PL/SQL コードで効果を発揮します。CPU バウンドな計算処理では 2〜10 倍の高速化が報告されることもあります。ただし SQL 文の実行速度には影響しないため、SQL 主体のコードでは効果が限定的です。

この記事でわかること

  • INTERPRETED モードと NATIVE モードの違いと仕組み
  • PLSQL_CODE_TYPE でセッション・システムレベルのコンパイルモードを変更する方法
  • 既存のプロシージャ・パッケージを NATIVE モードに再コンパイルする方法
  • ネイティブコンパイルが効果的な処理と効果が薄い処理
  • DBA_PLSQL_OBJECT_SETTINGS でコンパイルモードを確認する方法
  • 全オブジェクトを一括で NATIVE に変更するスクリプト
スポンサーリンク

INTERPRETED モードと NATIVE モードの違い

項目 INTERPRETED モード NATIVE モード
コンパイル結果 Oracle バイトコード(中間コード) OS ネイティブ機械語(共有ライブラリ)
実行速度(計算処理) バイトコードインタープリタで実行 CPU が直接実行するため高速
SQL 文の速度 変わらない 変わらない(SQL はデータベースエンジンが処理)
コンパイル時間 速い C コンパイラを使うためやや遅い
デバッグ DBMS_DEBUG / DBMS_PROFILER が使える 一部のデバッグツールが使えない場合がある
デフォルト(Oracle 11g 以降) PLSQL_CODE_TYPE のデフォルトは NATIVE
Oracle 11g 以降のデフォルト
Oracle 11g 以降では PLSQL_CODE_TYPE のデフォルト値が NATIVE に変更されました。そのため Oracle 11g 以降で作成したプロシージャは、デフォルトでネイティブコンパイルされています。移行前の古い環境から移行してきた場合や、明示的に INTERPRETED にしたコードが混在していないかを確認する価値があります。

PLSQL_CODE_TYPE の設定

セッション・システムレベルでコンパイルモードを設定する
-- 現在のデフォルトコンパイルモードを確認する
SHOW PARAMETER plsql_code_type;
-- または
SELECT name, value FROM V$PARAMETER WHERE name = 'plsql_code_type';

-- セッションレベルで NATIVE に変更する(このセッションでコンパイルするオブジェクトに適用)
ALTER SESSION SET PLSQL_CODE_TYPE = NATIVE;

-- セッションレベルで INTERPRETED に戻す(デバッグ時)
ALTER SESSION SET PLSQL_CODE_TYPE = INTERPRETED;

-- システムレベルで変更する(新規コンパイルのデフォルトになる)
ALTER SYSTEM SET PLSQL_CODE_TYPE = NATIVE SCOPE=BOTH;
-- SCOPE=BOTH: spfile と現在のインスタンスの両方に適用

-- NATIVE モードにしてコンパイルする
ALTER SESSION SET PLSQL_CODE_TYPE = NATIVE;

CREATE OR REPLACE PROCEDURE calc_intensive AS
    v_result NUMBER := 0;
BEGIN
    FOR i IN 1..1000000 LOOP
        v_result := v_result + SQRT(i) * LOG(10, i + 1);
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('結果: ' || v_result);
END calc_intensive;
/
-- このプロシージャは NATIVE モードでコンパイルされる

既存オブジェクトを NATIVE モードに再コンパイルする

ALTER PROCEDURE / ALTER PACKAGE で NATIVE 再コンパイルする
-- 特定のプロシージャを NATIVE で再コンパイルする
ALTER PROCEDURE hr.process_monthly_sales COMPILE PLSQL_CODE_TYPE=NATIVE REUSE SETTINGS;

-- パッケージ本体を NATIVE で再コンパイルする
ALTER PACKAGE hr.batch_pkg COMPILE BODY PLSQL_CODE_TYPE=NATIVE REUSE SETTINGS;

-- コンパイルモードを確認する
SELECT object_name, object_type, plsql_code_type
FROM ALL_PLSQL_OBJECT_SETTINGS
WHERE owner = 'HR'
  AND object_name IN ('PROCESS_MONTHLY_SALES', 'BATCH_PKG')
ORDER BY object_name, object_type;
-- PLSQL_CODE_TYPE: 'NATIVE' または 'INTERPRETED'
スキーマ内の全オブジェクトを NATIVE に一括再コンパイルする
-- スキーマ内の全プロシージャ・ファンクション・パッケージを NATIVE で再コンパイルする
DECLARE
    v_owner VARCHAR2(30) := 'HR';   -- 対象スキーマ
BEGIN
    FOR obj IN (
        SELECT object_name, object_type
        FROM ALL_OBJECTS
        WHERE owner = v_owner
          AND object_type IN ('PROCEDURE', 'FUNCTION', 'PACKAGE', 'PACKAGE BODY', 'TRIGGER')
          AND status = 'VALID'
        ORDER BY object_type, object_name
    ) LOOP
        BEGIN
            EXECUTE IMMEDIATE
                'ALTER ' || obj.object_type || ' ' || v_owner || '.' || obj.object_name ||
                ' COMPILE' ||
                CASE obj.object_type
                    WHEN 'PACKAGE BODY' THEN ' BODY'
                    ELSE ''
                END ||
                ' PLSQL_CODE_TYPE=NATIVE REUSE SETTINGS';
        EXCEPTION
            WHEN OTHERS THEN
                DBMS_OUTPUT.PUT_LINE(
                    '再コンパイル失敗: ' || obj.object_type || ' ' || obj.object_name ||
                    ' - ' || SQLERRM);
        END;
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('一括再コンパイル完了');
END;
/

ネイティブコンパイルの効果が出る処理・出ない処理

効果が大きい処理

  • 数値演算ループ:統計計算・シミュレーション・行列演算など CPU バウンドな処理
  • 文字列処理:大量の SUBSTR / REPLACE / REGEXP_REPLACE を含む処理
  • 複雑な条件分岐:多数の IF/CASE による制御ロジック
  • 再帰処理:ツリー構造の探索など再帰的なプロシージャ呼び出し
効果が限定的な処理

  • SQL 主体の処理:SELECT / INSERT / UPDATE / DELETE の実行速度は変わらない(SQL エンジンが処理するため)
  • 待機が多い処理:I/O 待機・ネットワーク待機が主なボトルネックの場合は効果なし
  • DBMS_OUTPUT が多い:出力処理はネイティブコンパイルの対象外

まとめ

  • NATIVE モード:PL/SQL コードを OS ネイティブ機械語にコンパイルする。CPU バウンドな処理で顕著な高速化が期待できる
  • Oracle 11g 以降のデフォルト:PLSQL_CODE_TYPE のデフォルトは NATIVE。古いコードの INTERPRETED 混在を確認する
  • 既存オブジェクトの移行:ALTER … COMPILE PLSQL_CODE_TYPE=NATIVE REUSE SETTINGS で再コンパイルする
  • SQL の速度は変わらない:SQL 実行はデータベースエンジンが担当するため、ネイティブコンパイルの恩恵を受けない
  • デバッグ時は INTERPRETED に戻す:DBMS_PROFILER など一部ツールは NATIVE コードで制限がある場合がある

PL/SQL のボトルネックを特定する方法は PL/SQL プロファイラ完全ガイドを参照してください。PL/SQL の条件付きコンパイルでデバッグコードを切り替える方法は 条件付きコンパイル完全ガイドも参照してください。