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 以降では
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 の条件付きコンパイルでデバッグコードを切り替える方法は 条件付きコンパイル完全ガイドも参照してください。