DBMS_PARALLEL_EXECUTEパッケージを使用すると、表データをパラレルで増分更新できるようになります。
|
関連項目:
|
この章では、次の項目について説明します。
概要
セキュリティ・モデル
定数
ビュー
例外
例
このパッケージを使用すると、次の2つの手順で、表データをパラレルで増分更新できます。
表内の一連の行を、より小さいサイズのチャンクにグループ化します。
ユーザーが指定した文をこれらのチャンクに対してパラレルで実行し、各チャンクの処理の終了時にコミットします。
このパッケージでは、パラレル実行タスクという概念が導入されています。このタスクによって、PL/SQLブロックのパラレル実行(通常は表データの更新)に関連付けられている様々な手順がグループ分けされます。
すべてのパッケージのサブルーチン(GENERATE_TASK_NAMEファンクションとTASK_STATUSプロシージャを除く)はコミットを実行します。
DBMS_PARALLEL_EXECUTEは、PUBLICに付与されているSYS所有のパッケージです。
すべてのユーザーがパラレル実行タスクを作成または実行し、USERビューにアクセスできます。
ADM_PARALLEL_EXECUTE_TASKロールを持つユーザーは、管理ルーチン(ADM_という接頭辞で修飾されているもの)を実行し、DBAビューにアクセスすることができます。
管理ルーチンは別として、すべてのサブプログラムによって現行のユーザーが所有しているタスクが参照されます。
チャンクをパラレル実行するには、CREATE JOBシステム権限が必要です。
CHUNK_BY_SQL、RUN_TASK、RESUME_TASKサブプログラムは問合せを要求し、DBMS_SQLを使用して実行します。DBMS_SQLインタフェースの実行者は、問合せがSQLインジェクションを含んでいないことを確認する必要があります。
DBMS_PARALLEL_EXECUTEパッケージでは、次の表に示す定数が使用されます。
表107-1 DBMS_PARALLEL_EXECUTEの定数: チャンク・ステータス値
| 定数 | タイプ | 値 | 説明 |
|---|---|---|---|
|
|
|
1 |
チャンクが処理の対象として割り当てられています。 |
|
|
|
2 |
チャンクが正常に処理されました。 |
|
|
|
3 |
チャンクは処理されましたが、処理中にエラーが発生しました。 |
|
|
|
0 |
チャンクが割り当てられていません。 |
表107-2 DBMS_PARALLEL_EXECUTEの定数: タスク・ステータス値
| 定数 | タイプ | 値 | 説明 |
|---|---|---|---|
|
|
|
4 |
タスクに関連付けられている表はチャンクされていますが、どのチャンクも処理の対象として割り当てられていません。 |
|
|
|
2 |
タスクに割り当てられている表がチャンクされています。 |
|
|
|
3 |
チャンクに失敗しました。 |
|
|
|
8 |
パラレル実行を使用する場合にのみ該当し、ジョブ・スレーブがクラッシュしたか、またはデータベースが |
|
|
|
1 |
タスクが |
|
|
|
6 |
すべてのチャンクがエラーなく処理されました。 |
|
|
|
7 |
すべてのチャンクが処理されましたが、エラーが発生した場合もあります。 |
|
|
|
5 |
一部のチャンクが処理の対象として割り当てられているか、または処理されています。 |
DBMS_PARALLEL_EXECUTEパッケージは、『Oracle Databaseリファレンス』にリストされているビューを使用します。
DBA_PARALLEL_EXECUTE_CHUNKS
DBA_PARALLEL_EXECUTE_TASKS
USER_PARALLEL_EXECUTE_CHUNKS
USER_PARALLEL_EXECUTE_TASKS
次の表に、DBMS_PARALLEL_EXECUTEで発生する例外を示します。
表107-3 DBMS_PARALLEL_EXECUTEで発生する例外
| 例外 | エラー・コード | 説明 |
|---|---|---|
|
|
29499 |
指定されたチャンクが存在しません。 |
|
|
29497 |
同じタスク名が既存のタスクによって使用されています。 |
|
|
29492 |
|
|
|
29495 |
実行の再開を試行しますが、タスクが |
|
|
29494 |
|
|
|
29493 |
チャンク・ステータスへの無効な値の設定を試行します。 |
|
|
29491 |
表が物理表ではないか、またはIOTの場合に、ROWIDごとに表のチャンクを試行します。 |
|
|
29490 |
ユーザーには、必要な |
|
|
29498 |
指定された |
次の例では、Oracle Databaseサンプル・スキーマについてのマニュアルのHuman Resources (HR)スキーマに関して実行します。JOB SYSTEM権限でHRスキーマを作成することが、要求されます。
ROWIDごとのチャンク
次の例は、このパッケージの最も一般的な使用方法を示しています。RUN_TASKプロシージャをコールした後、エラーをチェックし、エラーを検出した場合は再実行しています。
DECLARE
l_sql_stmt VARCHAR2(1000);
l_try NUMBER;
l_status NUMBER;
BEGIN
-- Create the TASK
DBMS_PARALLEL_EXECUTE.CREATE_TASK ('mytask');
-- Chunk the table by ROWID
DBMS_PARALLEL_EXECUTE.CREATE_CHUNKS_BY_ROWID('mytask', 'HR', 'EMPLOYEES', true, 100);
-- Execute the DML in parallel
l_sql_stmt := 'update EMPLOYEES e
SET e.salary = e.salary + 10
WHERE rowid BETWEEN :start_id AND :end_id';
DBMS_PARALLEL_EXECUTE.RUN_TASK('mytask', l_sql_stmt, DBMS_SQL.NATIVE,
parallel_level => 10);
-- If there is an error, RESUME it for at most 2 times.
L_try := 0;
L_status := DBMS_PARALLEL_EXECUTE.TASK_STATUS('mytask');
WHILE(l_try < 2 and L_status != DBMS_PARALLEL_EXECUTE.FINISHED)
LOOP
L_try := l_try + 1;
DBMS_PARALLEL_EXECUTE.RESUME_TASK('mytask');
L_status := DBMS_PARALLEL_EXECUTE.TASK_STATUS('mytask');
END LOOP;
-- Done with processing; drop the task
DBMS_PARALLEL_EXECUTE.DROP_TASK('mytask');
END;
/
ユーザー指定のSQLごとのチャンク
ユーザーはCREATE_CHUNKS_BY_SQLプロシージャを使用して、チャンク・アルゴリズムを指定できます。次の例は、同じmanager_idを持つ行が一緒にまとめられ、1つのチャンクとして処理されることを示しています。
DECLARE
l_chunk_sql VARCHAR2(1000);
l_sql_stmt VARCHAR2(1000);
l_try NUMBER;
l_status NUMBER;
BEGIN
-- Create the TASK
DBMS_PARALLEL_EXECUTE.CREATE_TASK ('mytask');
-- Chunk the table by MANAGER_ID
l_chunk_sql := 'SELECT distinct manager_id, manager_id FROM employees';
DBMS_PARALLEL_EXECUTE.CREATE_CHUNKS_BY_SQL('mytask', l_chunk_sql, false);
-- Execute the DML in parallel
-- the WHERE clause contain a condition on manager_id, which is the chunk
-- column. In this case, grouping rows is by manager_id.
l_sql_stmt := 'update EMPLOYEES e
SET e.salary = e.salary + 10
WHERE manager_id between :start_id and :end_id';
DBMS_PARALLEL_EXECUTE.RUN_TASK('mytask', l_sql_stmt, DBMS_SQL.NATIVE,
parallel_level => 10);
-- If there is error, RESUME it for at most 2 times.
L_try := 0;
L_status := DBMS_PARALLEL_EXECUTE.TASK_STATUS('mytask');
WHILE(l_try < 2 and L_status != DBMS_PARALLEL_EXECUTE.FINISHED)
Loop
L_try := l_try + 1;
DBMS_PARALLEL_EXECUTE.RESUME_TASK('mytask');
L_status := DBMS_PARALLEL_EXECUTE.TASK_STATUS('mytask');
END LOOP;
-- Done with processing; drop the task
DBMS_PARALLEL_EXECUTE.DROP_TASK('mytask');
end;
/
ユーザー定義フレームワークでのチャンクの実行
チャンクは、RUN_TASKプロシージャを使用せずに、独自に定義したフレームワークで実行できます。次の例は、GET_ROWID_CHUNKプロシージャ、EXECUTE IMMEDIATE、SET_CHUNK_STATUSプロシージャを使用してチャンクを実行する方法を示しています。
DECLARE
l_sql_stmt varchar2(1000);
l_try number;
l_status number;
l_chunk_id number;
l_start_rowid rowid;
l_end_rowid rowid;
l_any_rows boolean;
CURSOR c1 IS SELECT chunk_id
FROM user_parallel_execute_chunks
WHERE task_name = 'mytask'
AND STATUS IN (DBMS_PARALLEL_EXECUTE.PROCESSED_WITH_ERROR,
DBMS_PARALLEL_EXECUTE.ASSIGNED);
BEGIN
-- Create the Objects, task, and chunk by ROWID
DBMS_PARALLEL_EXECUTE.CREATE_TASK ('mytask');
DBMS_PARALLEL_EXECUTE.CREATE_CHUNKS_BY_ROWID('mytask', 'HR', 'EMPLOYEES', true, 100);
l_sql_stmt := 'update EMPLOYEES e
SET e.salary = e.salary + 10
WHERE rowid BETWEEN :start_id AND :end_id';
-- Execute the DML in his own framework
--
-- Process each chunk and commit.
-- After processing one chunk, repeat this process until
-- all the chunks are processed.
--
<<main_processing>>
LOOP
--
-- Get a chunk to process; if there is nothing to process, then exit the
-- loop;
--
DBMS_PARALLEL_EXECUTE.GET_ROWID_CHUNK('mytask',
l_chunk_id,
l_start_rowid,
l_end_rowid,
l_any_rows);
IF (l_any_rows = false) THEN EXIT; END IF;
--
-- The chunk is specified by start_id and end_id.
-- Bind the start_id and end_id and then execute it
--
-- If no error occured, set the chunk status to PROCESSED.
--
-- Catch any exception. If an exception occured, store the error num/msg
-- into the chunk table and then continue to process the next chunk.
--
BEGIN
EXECUTE IMMEDIATE l_sql_stmt using l_start_rowid, l_end_rowid;
DBMS_PARALLEL_EXECUTE.SET_CHUNK_STATUS('mytask',l_chunk_id,
DBMS_PARALLEL_EXECUTE.PROCESSED);
EXCEPTION WHEN OTHERS THEN
DBMS_PARALLEL_EXECUTE.SET_CHUNK_STATUS('mytask', l_chunk_id,
DBMS_PARALLEL_EXECUTE.PROCESSED_WITH_ERROR, SQLCODE, SQLERRM);
END;
--
-- Finished processing one chunk; Commit here
--
COMMIT;
END LOOP;
表107-4 DBMS_PARALLEL_EXECUTEパッケージのサブプログラム
| サブプログラム | 説明 |
|---|---|
|
|
指定した所有者が所有している指定のタスクのすべてのチャンクを削除します。 |
|
|
指定したユーザーのタスクとすべての関連したチャンクを削除します。 |
|
|
タスク・ステータスを戻します。 |
|
|
指定した所有者のタスクと関連したジョブ・スレーブを停止します。 |
|
|
現行のユーザーのタスクを作成します。 |
|
CREATE_CHUNKS_BY_NUMBER_COLプロシージャ |
指定した列ごとに、指定したタスクに関連付けられている表をチャンクします。 |
|
|
|
|
|
ユーザー指定の |
|
|
タスクとすべての関連したチャンクを削除します。 |
|
|
タスクのチャンクを削除します。 |
|
|
タスクの一意の名前を戻します。 |
|
|
割り当てられていない |
|
|
割り当てられていない |
|
|
ステータスが |
|
|
RUN_TASKプロシージャがエラーで終了した場合に指定したタスクを再試行するか、またはクラッシュが発生した場合にタスクを再開します。 |
|
|
指定したSQL文をチャンクに対してパラレル実行します。 |
|
|
チャンクのステータスを設定します。 |
|
|
タスクと関連したジョブ・スレーブを停止します。 |
|
|
タスク・ステータスを戻します。 |
このファンクションは、タスク・ステータスを戻します。
このプロシージャは、指定した列ごとに、(指定したタスクに関連付けられている)表をチャンクします。指定する列はNUMBER列である必要があります。このプロシージャは、列のMIN値とMAX値を取得し、chunk_sizeに応じてその範囲を均等に分割します。チャンクは次のとおりです。
START_ID END_ID --------------------------- --------------------------- min_id_val min_id_val+1*chunk_size-1 min_id_val+1*chunk_size min_id_val+2*chunk_size-1 … … min_id_val+i*chunk_size max_id_val
このプロシージャは、(指定したタスクに関連付けられている)表をROWIDごとにチャンクします。num_rowおよびnum_blockは、各チャンクのサイズの大まかな指針です。チャンクされる表は、ビューおよび表ファンクションを含む物理ROWIDのある物理表である必要があります。索引構成表は使用できません。
このプロシージャは、ユーザー指定のSELECT文によって、(指定したタスクに関連付けられている)表をチャンクします。各チャンクの範囲を戻すSELECT文には、start_idとend_idの2つの列が含まれている必要があります。タスクがROWIDごとにチャンクされる場合、これらの2つの列はROWIDタイプである必要があります。タスクがNUMBER列ごとにチャンクされる場合、これらの2つの列はNUMBERタイプである必要があります。このプロシージャによって、ユーザーは、ユーザー定義のチャンク・アルゴリズムを柔軟にデプロイできるようになります。
このファンクションは、タスクの一意の名前を戻します。名前はprefixNの形式で示され、Nは順序番号です。接頭辞が指定されていない場合にデフォルトで生成される名前はTASK$_1、TASK$_2、TASK$_3などになります。接頭辞として'SCOTT'が指定されている場合の名前は、SCOTT1、SCOTT2などになります。
このプロシージャは、割り当てられていないNUMBERチャンクを取得し、ASSIGNEDに変更します。割り当てるチャンクがない場合、any_rowsはFALSEに設定されます。それ以外の場合、チャンクのchunk_id、startおよびend_idは、OUTパラメータとして戻されます。DBMS_PARALLEL_EXECUTE_CHUNKS$内のチャンク情報が次のように更新され、STATUSはASSIGNEDとなり、START_TIMESTAMPには現在の時間が記録され、END_TIMESTAMPは消去されます。
構文
DBMS_PARALLEL_EXECUTE.GET_NUMBER_COL_CHUNK ( task_name IN VARCHAR2, chunk_id OUT NUMBER, start_rowid OUT ROWID, end_id OUT ROWID, any_rows OUT BOOLEAN);
このプロシージャは、割り当てられていないROWIDチャンクを取得し、ASSIGNEDに変更します。割り当てるチャンクがない場合、any_rowsはFALSEに設定されます。それ以外の場合、チャンクのchunk_id、startおよびend_idは、OUTパラメータとして戻されます。DBMS_PARALLEL_EXECUTE_CHUNKS$内のチャンク情報が次のように更新され、STATUSはASSIGNEDとなり、START_TIMESTAMPには現在の時間が記録され、END_TIMESTAMPは消去されます。
構文
DBMS_PARALLEL_EXECUTE.GET_ROWID_CHUNK ( task_name IN VARCHAR2, chunk_id OUT NUMBER, start_rowid OUT ROWID, end_id OUT ROWID, any_rows OUT BOOLEAN);
このプロシージャは、RUN_TASKプロシージャがエラーで終了した場合は指定されたタスクを再試行し、クラッシュが発生した場合はタスクを再開します。タスクがCRASHEDまたはFINISHED_WITH_ERRORの状態の場合にのみ、このプロシージャを起動できます。クラッシュしたシリアル実行の場合、状態は処理中のままになります。FORCEオプションを使用すると、PROCESSING状態の任意のタスクを再開できます。ただし、クラッシュが発生したかどうかの確認は、各自で行います。このプロシージャによって、処理されていないチャンクの処理が再開されます。また、PROCESSED_WITH_ERRORまたはASSIGNED(クラッシュが原因)状態のチャンクは、コミットしなかったため処理されます。このプロシージャは、RUN_TASKプロシージャと同じ引数を使用します。task_nameを唯一の入力引数として使用するオーバーロードは、前のRUN_TASKプロシージャまたはRESUME_TASKプロシージャのコールで指定された引数を再利用します。
構文
DBMS_PARALLEL_EXECUTE.RESUME_TASK ( task_name IN VARCHAR2, sql_stmt IN CLOB, language_flag IN NUMBER, edition IN VARCHAR2 DEFAULT NULL, apply_crossedition_trigger IN VARCHAR2 DEFAULT NULL, fire_apply_trigger IN BOOLEAN DEFAULT TRUE, parallel_level IN NUMBER DEFAULT 0, job_class IN VARCHAR2 DEFAULT 'DEFAULT_JOB_CLASS', force IN BOOLEAN DEFAULT FALSE); DBMS_PARALLEL_EXECUTE.RESUME_TASK ( task_name IN VARCHAR2, force IN BOOLEAN DEFAULT FALSE);
パラメータ
表107-19 RESUME_TASKプロシージャのパラメータ
| パラメータ | 説明 |
|---|---|
|
|
タスクの名前。 |
|
|
SQL文。 |
|
|
OracleでSQL文を処理する方法を決定します。次のオプションが認識されます。
|
|
|
文を実行するエディションを指定します。デフォルトは現行のエディションです。 |
|
|
指定したSQLに適用する転送crosseditionトリガーの未修飾の名前を指定します。この名前は、文が実行されるエディションおよび |
|
|
指定した |
|
|
パラレル・ジョブの数を指定します。シリアル実行する場合はゼロを指定し、デフォルトの並列度を使用する場合は |
|
|
パラレル実行の場合、ジョブはすべて指定したジョブ・クラスに属します。 |
|
|
|
例
チャンク表に次のチャンク範囲が含まれているとします。
START_ID END_ID --------------------------- --------------------------- 1 10 11 20 21 30
指定したSQL文は、次のとおりです。
UPDATE employees
SET salary = salary + 10
WHERE e.employee_id BETWEEN :start_id AND :end_id
このプロシージャは、次の文をパラレル実行します。
UPDATE employees
SET salary =.salary + 10 WHERE employee_id BETWEEN 1 and 10;
COMMIT;
UPDATE employees
SET salary =.salary + 10 WHERE employee_id between 11 and 20;
COMMIT;
UPDATE employees
SET salary =.salary + 10 WHERE employee_id between 21 and 30;
COMMIT;
このプロシージャは、指定した文(sql_stmt)をチャンクに対してパラレル実行します。各チャンクの処理後に、コミットが行われます。指定する文には、それぞれstart_idおよびend_idと呼ばれる2つのプレースホルダが必要で、これらは処理されるチャンクの範囲を表します。各プレースホルダのタイプは、ROWIDベースのチャンクを使用した場合はROWID、NUMBERベースのチャンクを使用した場合はNUMBERである必要があります。
構文
DBMS_PARALLEL_EXECUTE.RUN_TASK ( task_name IN VARCHAR2, sql_stmt IN CLOB, language_flag IN NUMBER, edition IN VARCHAR2 DEFAULT NULL, apply_crossedition_trigger IN VARCHAR2 DEFAULT NULL, fire_apply_trigger IN BOOLEAN DEFAULT TRUE, parallel_level IN NUMBER DEFAULT 0, job_class IN VARCHAR2 DEFAULT 'DEFAULT_JOB_CLASS');
パラメータ
表107-20 RUN_TASKプロシージャのパラメータ
| パラメータ | 説明 |
|---|---|
|
|
タスクの名前。 |
|
|
SQL文。 |
|
|
OracleでSQL文を処理する方法を決定します。次のオプションが認識されます。
|
|
|
文を実行するエディションを指定します。デフォルトは現行のエディションです。 |
|
|
指定したSQLに適用する転送crosseditionトリガーの未修飾の名前を指定します。この名前は、文が実行されるエディションおよび |
|
|
指定した |
|
|
パラレル・ジョブの数を指定します。シリアル実行する場合はゼロを指定し、デフォルトの並列度を使用する場合は |
|
|
パラレル実行の場合、ジョブは指定したジョブ・クラスに属します。 |
使用上の注意
SQL文は現行のユーザーとして実行されます。
このサブプログラムはエラー上で再実行されることがあるため、同等ではないRUN_TASKに文を送信する場合は細心の注意が必要です。
チャンクはDBMS_SCHEDULERジョブ・スレーブによってパラレル実行できます。したがって、パラレル実行にはCREATE JOBシステム権限が必要です。ジョブ・スレーブは現行のユーザーに基づいて作成されます。ジョブ・スレーブのデフォルト数は、Oracleのパラメータcpu_countおよびparallel_threads_per_cpuの積として計算されます。Real Application Clustersのインストールでは、ジョブ・スレーブの数はクラスタ内の各ノードの個々の設定の合計になります。このプロシージャは、すべてのチャンクが処理されたときにのみ戻されます。パラレル実行の場合、このプロシージャはジョブ・スレーブがすべて完了したときにのみ戻されます。
例
チャンク表に次のチャンク範囲が含まれているとします。
START_ID END_ID --------------------------- --------------------------- 1 10 11 20 21 30
指定したSQL文は、次のとおりです。
UPDATE employees
SET salary = salary + 10
WHERE e.employee_id BETWEEN :start_id AND :end_id
このプロシージャは、次の文をパラレル実行します。
UPDATE employees
SET salary =.salary + 10 WHERE employee_id BETWEEN 1 and 10;
COMMIT;
UPDATE employees
SET salary =.salary + 10 WHERE employee_id between 11 and 20;
COMMIT;
UPDATE employees
SET salary =.salary + 10 WHERE employee_id between 21 and 30;
COMMIT;
このプロシージャは、チャンクのステータスを設定します。チャンクのSTART_TIMESTAMPおよびEND_TIMESTAMPは、新しいステータスに応じて更新されます。
Value of the new Status Side Effect
--------------------------- ---------------------------
UNASSIGNED START_TIMESTAMP and END_TIMESTAMP
will be cleared
ASSIGNED START_TIMESTAMP will be the current time
and END_TIMESTAMP will be cleared.
PROCESSED or PROCESSED_WITH_ERROR The current time will be recorded
in END_TIMESTAMP