Oracle の並列実行(Parallel Execution)は、大量データのフルスキャン・集計・ソートを複数の並列プロセスに分散処理させることで実行時間を短縮する機能です。データウェアハウス・バッチ処理・大規模テーブルの一括更新などに効果的です。
ただし並列実行は CPU・I/O リソースを大量消費するため、OLTP 環境での多用は他のセッションへの影響が大きくなります。用途を絞って活用することが重要です。
この記事でわかること
- 並列実行の仕組み(クエリコーディネーターとパラレルサーバーの役割)
- PARALLEL ヒントと PARALLEL 句で並列度(DOP)を指定する方法
- 並列 DML(INSERT / UPDATE / DELETE)を有効にして実行する方法
- PARALLEL_DEGREE_POLICY パラメータで自動並列度管理を設定する
- V$PX_SESSION / V$PQ_SESSTAT で並列実行の状況を監視する
- 並列実行のトラブル(パラレルサーバー不足・シリアル実行へのダウングレード)への対処
並列実行の仕組み
並列実行では QC(Query Coordinator)が全体を制御し、パラレルサーバー(PX Server)と呼ばれる複数のプロセスが実際の処理を分担します。
- DOP(Degree of Parallelism):並列度。DOP=4 なら最大 4 つの PX Server が使われる(Producer と Consumer の組み合わせで最大 DOP×2 プロセスになる場合もある)
- デフォルトの DOP:テーブルやインデックスに設定された PARALLEL 句、またはヒントで指定。未指定なら PARALLEL_DEGREE_POLICY に従う
- シリアルへのダウングレード:要求した PX Server が確保できない場合、デフォルトはシリアル実行に自動降格する(PARALLEL_MIN_PERCENT 設定で制御可能)
PARALLEL ヒントで並列クエリを実行する
PARALLEL ヒントの基本的な使い方
-- 特定のテーブルを DOP=4 で並列フルスキャンする
SELECT /*+ PARALLEL(sales, 4) */
product_id, SUM(amount) AS total_sales
FROM sales
GROUP BY product_id;
-- 複数テーブルに並列を指定する
SELECT /*+ PARALLEL(s, 4) PARALLEL(p, 4) */
p.product_name, SUM(s.amount)
FROM sales s
JOIN products p ON s.product_id = p.product_id
GROUP BY p.product_name;
-- DOP を自動設定(Oracle がシステムリソースに応じて決定)
SELECT /*+ PARALLEL(sales, DEFAULT) */ COUNT(*) FROM sales;
-- テーブル名を省略して SQL 全体に並列を指定する(Oracle 11g 以降)
SELECT /*+ PARALLEL */ COUNT(*) FROM sales;
-- ただしどのテーブルに適用されるか不明確なため、テーブル名を明示する方が推奨
-- 並列を無効化する(テーブルに PARALLEL が設定されていても強制シリアル)
SELECT /*+ NO_PARALLEL(sales) */ * FROM sales WHERE sale_id = 123;
テーブルに PARALLEL を永続設定する
DDL で PARALLEL 句を設定・変更する
-- テーブル作成時に PARALLEL を設定する
CREATE TABLE sales_history (
sale_id NUMBER,
sale_date DATE,
amount NUMBER(12, 2)
)
PARALLEL 4; -- デフォルト DOP = 4
-- 既存テーブルの PARALLEL を変更する
ALTER TABLE sales PARALLEL 8;
-- 並列を無効化する(シリアルに戻す)
ALTER TABLE sales NOPARALLEL;
-- テーブルの PARALLEL 設定を確認する
SELECT table_name, degree, instances
FROM DBA_TABLES
WHERE owner = 'SALES'
ORDER BY table_name;
-- degree = 1 → NOPARALLEL
-- degree = 4 → PARALLEL 4
-- degree = DEFAULT → PARALLEL(DOP はシステム設定に従う)
並列 DML(PDML)を有効にして実行する
並列クエリ(SELECT)はデフォルトで使えますが、並列 DML(INSERT・UPDATE・DELETE)はセッションレベルで明示的に有効化が必要です。PDML ではテーブルがパーティション分割されている場合に最大の効果があります。
並列 DML を有効にして大量データを一括処理する
-- セッションで並列 DML を有効化する ALTER SESSION ENABLE PARALLEL DML; -- 並列 INSERT(APPEND ヒントと組み合わせてダイレクト・パス・インサートを使う) INSERT /*+ PARALLEL(sales_archive, 4) APPEND */ INTO sales_archive SELECT * FROM sales WHERE sale_date < DATE '2023-01-01'; COMMIT; -- 並列 DML 後はコミットが必要(テーブルロックを解放) -- 並列 UPDATE(パーティション表で特に効果的) UPDATE /*+ PARALLEL(sales, 4) */ sales SET status = 'ARCHIVED' WHERE sale_date < DATE '2023-01-01'; COMMIT; -- セッションで並列 DML を無効化する ALTER SESSION DISABLE PARALLEL DML; -- ヒントで特定の DML のみ並列化する(セッション設定に関わらず) INSERT /*+ ENABLE_PARALLEL_DML PARALLEL(t, 4) */ INTO t SELECT * FROM s;
並列 DML の注意点
- 並列 DML 中はテーブルに排他ロックがかかる。他のセッションは DML や SELECT ができなくなる可能性がある
- ロールバックが必要になった場合は UNDO 表領域を大量消費する
- 並列 DML 後のコミット前に同じテーブルを参照する DML・SELECT はエラーになる(ORA-12838)
- APPEND ヒントとの組み合わせでダイレクト・パス・インサートになり、REDO ログ生成を最小化できる(NOLOGGING テーブルの場合)
PARALLEL_DEGREE_POLICY で自動並列度管理を設定する
並列度ポリシーの確認と変更
-- 現在の設定を確認する SHOW PARAMETER parallel_degree_policy; -- 設定値の説明: -- MANUAL : ヒントまたはテーブル設定の DOP のみ使用(デフォルト) -- LIMITED : 統計が古い場合にのみ自動 DOP を適用 -- AUTO : Oracle がリソースに応じて DOP を自動決定(Tuning Pack が必要) -- ADAPTIVE : AUTO に加え、実行中に DOP を動的調整 -- セッションレベルで変更する ALTER SESSION SET parallel_degree_policy = 'AUTO'; -- システムレベルで変更する(本番では影響を十分検証してから) ALTER SYSTEM SET parallel_degree_policy = 'MANUAL' SCOPE=BOTH; -- 同時実行できる並列サーバー数の上限を確認する SHOW PARAMETER parallel_max_servers; -- デフォルト: CPU 数 × 10 SHOW PARAMETER parallel_min_servers; -- 起動時に確保するサーバー数
並列実行の状況を監視する
V$PX_SESSION で現在の並列セッションを確認する
-- 現在実行中の並列セッションを確認する
SELECT
qcsid, -- QC(クエリコーディネーター)のセッション ID
qcserial#, -- QC のシリアル番号
sid, -- パラレルサーバーのセッション ID
serial#,
server_group, -- 並列グループ
server_set, -- サーバーセット(Producer=1, Consumer=2)
degree, -- 要求した DOP
actual_degree, -- 実際に使用している DOP
p.program
FROM V$PX_SESSION ps
JOIN V$SESSION s ON ps.sid = s.sid
JOIN V$PROCESS p ON s.paddr = p.addr
ORDER BY qcsid, server_set, sid;
-- 並列クエリのパフォーマンス統計を確認する
SELECT
name,
value
FROM V$PQ_SESSTAT
WHERE name IN (
'Queries Parallelized', -- 並列化されたクエリ数
'DFO Trees', -- DFO ツリー数
'Sessions Active' -- アクティブな PX セッション数
);
-- 実行計画で並列操作を確認する
EXPLAIN PLAN FOR
SELECT /*+ PARALLEL(sales, 4) */ COUNT(*) FROM sales;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(format => 'TYPICAL'));
-- :TQ10000 などの列転送識別子が表示されれば並列実行
-- PX COORDINATOR・PX SEND・PX RECEIVE 操作が現れる
まとめ
- /*+ PARALLEL(table, n) */:特定テーブルの DOP を指定。NOPARALLEL で並列を抑制する
- ALTER TABLE t PARALLEL n:テーブルにデフォルト DOP を永続設定する
- 並列 DML:ALTER SESSION ENABLE PARALLEL DML が必要。コミット前に同テーブルへの DML/SELECT 不可(ORA-12838)
- PARALLEL_DEGREE_POLICY=AUTO:Oracle が自動で DOP を決定(Tuning Pack ライセンスが必要)
- V$PX_SESSION:実行中の並列セッションと実際の DOP をリアルタイム監視できる
- OLTP 環境での多用は避け、バッチ・DWH 処理などリソース余裕のある時間帯に限定することを推奨する
実行計画で並列操作の詳細を確認する方法は DBMS_XPLAN完全ガイドを参照してください。並列実行のリソース制御は Database Resource Manager完全ガイドと組み合わせて使うと効果的です。