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
パッケージでは、次の表に示す定数が使用されます。
表101-1 DBMS_PARALLEL_EXECUTEの定数 - チャンク・ステータス値
定数 | タイプ | 値 | 説明 |
---|---|---|---|
|
|
1 |
チャンクが処理の対象として割り当てられています。 |
|
|
2 |
チャンクが正常に処理されました。 |
|
|
3 |
チャンクは処理されましたが、処理中にエラーが発生しました。 |
|
|
0 |
チャンクが割り当てられていません。 |
表101-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
で発生する例外を示します。
表101-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 /*+ ROWID (dda) */ 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 /*+ ROWID (dda) */ 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 /*+ ROWID (dda) */ 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;
表101-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);
パラメータ
表101-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
である必要があります。指定する文は、冪等でないかぎり、コミットしないでください。
SQL文は現行のユーザーとして実行されます。
apply_crossedition_trigger
を指定した場合、DBMS_CROSSEDITION_TRIGGER
.IS_APPLYING
はSQLを実行するセッションに対してTRUEを戻します。したがって、パラレル実行の場合、DBMS_CROSSEDITION_TRIGGER
.IS_APPLYING
はジョブ・スレーブ・セッションでTRUEを戻します。
チャンクはDBMS_SCHEDULER
ジョブ・スレーブによってパラレル実行できます。したがって、パラレル実行にはCREATE
JOB
システム権限が必要です。ジョブ・スレーブは現行のユーザーに基づいて作成されます。ジョブ・スレーブのデフォルト数は、Oracleのパラメータcpu_count
およびparallel_threads_per_cpu
の積として計算されます。Real Application Clustersのインストールでは、ジョブ・スレーブの数はクラスタ内の各ノードの個々の設定の合計になります。このプロシージャは、すべてのチャンクが処理されたときにのみ戻されます。パラレル実行の場合、このプロシージャはジョブ・スレーブがすべて完了したときにのみ戻されます。
構文
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');
パラメータ
表101-20 RUN_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;
このプロシージャは、チャンクのステータスを設定します。チャンクの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