8.8 パラレル実行のチューニングのヒント

この項では、パラレル実行環境でのパフォーマンスを向上させるための様々な方法を説明します。

この項では、次の項目について説明します。

8.8.1 パラレル実行計画の実装

優れたパラレル実行計画の実装は、高いパフォーマンスを確実にするために重要となります。

優れた計画のための推奨事項を次に示します。

  • システム内で起こっていることを理解するために、単純な設定を実装します。

  • リソース・マネージャを使用して、システムに負担をかけることなく一定量の処理リソースを各グループに割り当てるよう、コンシューマ・グループの最大並列度(DOP)を指定します。リソース・マネージャ・ポリシーは、パラレル実行を使用してシステムを統御する場合、およびSQL文を必ずパラレルで実行できるようにするために必要となります。

  • パラレル実行に使用できるようにするシステム・リソースの量を計画の基礎とします。パラメータPARALLEL_MAX_SERVERSおよびPARALLEL_SERVERS_TARGETの値を調整して、システム内で実行されるパラレル実行(PX)サーバーの数を制限します。

  • ETL (抽出、変換およびロード)計画ではなくELT (抽出、ロードおよび変換)計画の採用を検討します。

  • より高速なデータ・ロードのために、CTASやIASなど、パラレルSQL文で外部表を使用します。

8.8.2 パラレルでの表の作成および移入によるパフォーマンスの最適化

大量の結果セットを取得するパラレル実行パフォーマンスを最適化するには、パラレルで表を作成および移入します。

Oracle Databaseは、結果をユーザー・プロセスにパラレルで返すことはできません。問合せが多数の行を返す場合、問合せの実行は実際に速くなることもあります。ただし、ユーザー・プロセスは行の受取りをシリアルでしか実行できません。大量の結果セットを取得する問合せのパラレル実行パフォーマンスを最適化するには、PARALLEL CREATE TABLE AS SELECTまたはダイレクト・パスINSERTを使用して結果セットをデータベースに格納します。ユーザーは結果セットを後からシリアルで確認できます。

SELECTをパラレルで実行してもCREATE文には影響しません。ただし、CREATE文がパラレルで実行される場合、オプティマイザはSELECTもパラレルで実行しようとします。

パラレルのCREATE TABLE AS SELECTNOLOGGINGオプションと組み合せると、次の例のように大変効率のよい中間表機能が提供されます。

CREATE TABLE summary PARALLEL NOLOGGING AS SELECT dim_1, dim_2 ..., 
SUM (meas_1)
FROM facts GROUP BY dim_1, dim_2;

これらの表も、パラレルINSERTを使用して増分的にロードできます。中間表を活用するには、次の方法を使用します。

  • 通常の副問合せは、1回計算すると、何度でも参照できます。これを利用すると、スター・スキーマに対する一部の問合せ(特に、選択のためのWHERE句を含む述語のない問合せ)をより適切にパラレル化できるようになります。スター型変換を使用する、選択のためのWHERE句を含む述語のあるスター問合せは、SQLを変更しなくても自動的に効率よくパラレル化できます。

  • アプリケーションレベルのチェックポイントまたは再起動を実現するために、複雑な問合せを単純なステップに分解します。たとえば、1TBのデータベースに対して複雑な複数表の結合を実行すると、数十時間に及ぶ可能性があります。この問合せの最中に障害が発生すると、最初からやりなおすことになります。CREATE TABLE AS SELECTまたはPARALLEL INSERT AS SELECTを使用してこの問合せを再作成し、数時間ずつ実行される単純な問合せの順序を作成します。システム障害が発生しても、最後に完了したステップの次から問合せを再起動できます。

  • 元の表の不要な行を省いた新しい表を作成してから、元の表を削除することにより、手動パラレル削除操作を効率よく実装します。または、元の表から行を直接削除する、便利なパラレル削除機能を使用することもできます。

  • 効率のよいマルチディメンション・ドリルダウン分析のためにサマリー表を作成します。たとえば、サマリー表には、月、種類、地域、販売担当者ごとにグループ化された収益の合計を含めることができます。

  • 行チェーンの消去や空き領域の圧縮などを行い、古い表を新しい表にコピーして、表を再編成します。この方法はエクスポートとインポートよりも速く、再ロードよりも容易です。

新たに作成した表でオプティマイザ統計を収集するにはDBMS_STATSパッケージを使用してください。I/Oボトルネックを回避するために、少なくともCPUと同数の物理ディスクに対してストライプ化された表領域を指定します。領域を割り当てるときに断片化を回避するために、表領域のファイル数はCPU数の倍数にする必要があります。

関連項目:

データ・ウェアハウスのパラレル実行の詳細は、『Oracle Databaseデータ・ウェアハウス・ガイド』を参照してください

8.8.3 EXPLAIN PLANを使用したパラレル操作計画の表示

EXPLAIN PLAN文を使用して、パラレル問合せの実行計画を表示します。

EXPLAIN PLANの出力で、COSTBYTESおよびCARDINALITY列にオプティマイザの情報が表示されます。utlxplp.sqlスクリプトを使用して、関連するすべてのパラレル情報と一緒にEXPLAIN PLAN出力を表示することもできます。

結合文のパラレル実行を最適化する方法がいくつかあります。システム構成を変更するか、この章で前に説明したようにパラメータを調整するか、DISTRIBUTIONヒントなどのヒントを使用します。

EXPLAIN PLANを使用する際の重要なポイントは次のとおりです。

  • オプティマイザの選択性見積りを確認します。問合せで1行しか生成されないとオプティマイザが予測する場合、ネステッド・ループを使用する傾向が高くなります。このとき、表が分析されていない可能性や、同一の表に対する複数の述語の相関関係についてオプティマイザの見積りが誤っている可能性があります。オプティマイザに正しい選択性を提供したり、オプティマイザに別の結合方法を使用させるために、統計やヒントを拡張することが必要な場合があります。

  • 低カーディナリティの結合キーに対するハッシュ結合を使用します。結合キーに固有の値が少ない場合、ハッシュ結合は最適ではない可能性があります。固有値の数が並列度(DOP)を下回る場合は、一部のパラレル問合せサーバーが特定の問合せの処理を行えないことがあります。

  • データの偏りを考慮します。結合キーに過度のデータの偏りがある場合、ハッシュ結合を行うと、一部のパラレル問合せサーバーに多くの作業が偏る可能性があります。オプティマイザによってBROADCAST分散方法が選択されなかった場合は、そのためのヒントの使用を検討してください。オプティマイザによってBROADCAST分散方法が考慮されるのは、OPTIMIZER_FEATURES_ENABLEを9.0.2以上に設定した場合のみです。詳細は、「V$PQ_TQSTAT」を参照してください。

8.8.3.1 例: EXPLAIN PLANを使用したパラレル操作の表示

EXPLAIN PLANを使用してパラレル操作を表示できます。

次の例は、オプティマイザがパラレル問合せを実行しようとする場合を示しています。

explain plan for 
  SELECT /*+ PARALLEL */ cust_first_name, cust_last_name 
   FROM customers c, sales s WHERE c.cust_id = s.cust_id;

----------------------------------------------------------
| Id  | Operation                       |  Name          |
----------------------------------------------------------
|   0 | SELECT STATEMENT                |                |
|   1 |  PX COORDINATOR                 |                |
|   2 |   PX SEND QC (RANDOM)           | :TQ10000       |
|   3 |    NESTED LOOPS                 |                |
|   4 |     PX BLOCK ITERATOR           |                |
|   5 |      TABLE ACCESS FULL          | CUSTOMERS      |
|   6 |     PARTITION RANGE ALL         |                |
|   7 |      BITMAP CONVERSION TO ROWIDS|                |
|   8 |       BITMAP INDEX SINGLE VALUE | SALES_CUST_BIX |
----------------------------------------------------------

Note
-----
   - automatic DOP: Computed Degree of Parallelism is 2

8.8.4 パラレルDMLのその他の考慮事項

このトピックでは、パラレルDML操作の使用に関するその他の考慮事項について説明します。

データ・ウェアハウスに対してパラレルの挿入、更新または削除操作を使用して、データ・ウェアハウス・データベースをリフレッシュする予定があるときは、物理データベースを設計する際にさらに考慮すべき項目があります。これらの考慮事項はパラレル実行操作には影響しません。これらの問題は次のとおりです。

8.8.4.1 パラレルDMLおよびダイレクト・パス制限

このトピックでは、パラレルおよびダイレクト・パス操作の制限について説明します。

パラレル制限に違反すると、操作はシリアルで実行されるだけです。ダイレクト・パスINSERT制限に違反すると、APPENDヒントが無視され、従来の挿入操作が実行されます。エラー・メッセージは返されません。

8.8.4.2 並列度の制限

使用しているOracle Databaseのソフトウェア・レベルに基づく並列度の制限があります。

パラレルDML itl不変プロパティのない表(Oracle9iリリース2 (9.2)よりも前に作成された表、またはCOMPATIBLE初期化パラメータを9.2より小さい値に設定して作成された表)については、並列度(DOP)はパーティションまたはサブパーティションの数と等しくなります。つまり、表がパーティション化されていない場合、問合せはシリアルで実行されます。このプロパティのない表を特定するには、次の文を発行します。

SELECT u.name, o.name FROM obj$ o, tab$ t, user$ u
 WHERE o.obj# = t.obj# AND o.owner# = u.user#
 AND bitand(t.property,536870912) != 536870912;

関連項目:

トランザクション表とも呼ばれるInterested Transaction List (ITL)の詳細は、『Oracle Database概要』を参照してください

8.8.4.3 INITRANSを増加するタイミング

特定の状況では、INITRANSの値を増やす必要があります。

グローバル索引がある場合、グローバル索引セグメントとグローバル索引ブロックは同じパラレルDML文のサーバー・プロセスによって共有されます。操作が同じ行に対して実行されなくても、サーバー・プロセスは同じ索引ブロックを共有できます。各サーバー・トランザクションは、索引ブロックに変更を行う前に、索引ブロック・ヘッダーの1つのトランザクション・エントリを必要とします。

この状況では、CREATE INDEX文またはALTER INDEX文を使用する際、INITRANS(各データ・ブロックに割り当てられるトランザクションの初期値)を、その索引に対する最大DOPなどの大きな値に設定する必要があります。

8.8.4.4 セグメントで使用可能なトランザクション空きリスト数の制限

ディクショナリ管理表領域のセグメントで使用可能なトランザクション空きリスト数には制限があります。

セグメントが作成されると、プロセス空きリストとトランザクション空きリストの数は固定され、変更できません。セグメント・ヘッダーでプロセス空きリストの数として大きな値を指定すると、それによって使用可能なトランザクション空きリストの数が制限されることがあります。この制限を避けるには、次にセグメント・ヘッダーを再作成するときに、プロセス空きリストの数を減らします。こうすると、セグメント・ヘッダーでトランザクション空きリストのための余裕ができます。

UPDATEおよびDELETE操作では、各サーバー・プロセスが独自のトランザクション空きリストを必要とする場合があります。このため、パラレルDMLのDOPは、表とDML文でメンテナンスする必要があるすべてのグローバル索引に対して使用可能な、トランザクション空きリストの最小数によって事実上制限されます。たとえば、表に25のトランザクション空きリストがあるとき、その表に2つのグローバル索引があり、1つの索引に50のトランザクション空きリスト、もう1つの索引に30のトランザクション空きリストがあるとすると、DOPの制限は25になります。この表のトランザクション空きリストが40であれば、DOPの制限は30になります。

STORAGE句のFREELISTSパラメータは、プロセス空きリストの数を設定するために使用されます。デフォルトではプロセス空きリストは作成されません。

トランザクション空きリストのデフォルト数はブロック・サイズによって異なります。たとえば、プロセス空きリストの数が明示的に設定されない場合、デフォルトでは4KBのブロックに対して約80のトランザクション空きリストになります。トランザクション空きリストの最小数は25です。

8.8.4.5 多数のREDOログの複数のアーカイバ

多数のREDOログをアーカイブするには、複数のアーカイバ・プロセスが必要です。

パラレルDDLおよびパラレルDML操作は、多数のREDOログを生成する場合があります。これらのREDOログのアーカイブは、1つのARCHプロセスでは間に合わない可能性があります。この問題を回避するため、複数のアーカイバ・プロセスを生成できます。これは、手動で行うこともジョブ・キューを使用して行うこともできます。

8.8.4.6 データベース・ライター・プロセス(DBWn)のワークロード

データベース・ライター・プロセスの数を増やす必要がある場合があります。

パラレルDML操作により、短時間でバッファ・キャッシュ内の多数のデータ、索引およびUNDOブロックの内容が使用されます。たとえば、次の構文でV$SYSTEM_EVENTビューを問い合せると、free_buffer_waitsの値が高く示されると想定します。

SELECT TOTAL_WAITS FROM V$SYSTEM_EVENT WHERE EVENT = 'FREE BUFFER WAITS';

この場合は、DBWnプロセスを増やすことの検討が必要です。空きバッファの待機時間がない場合、問合せによって行が返されません。

8.8.4.7 [NO]LOGGING句

[NO]LOGGING句を設定する際の考慮事項を理解してください。

[NO]LOGGING句は、表、パーティション、表領域および索引に適用されます。NOLOGGING句を使用すると、事実上、特定の操作(ダイレクト・パスINSERTなど)に対してログが生成されません。NOLOGGING属性はINSERT文のレベルでは指定されませんが、表、パーティション、索引または表領域に対してALTER文またはCREATE文を使用して指定されます。

表または索引にNOLOGGINGが設定されると、パラレルまたはシリアルのダイレクト・パスINSERT操作ではREDOログが生成されません。NOLOGGINGオプションが設定されて実行しているプロセスは、REDOが生成されないため、処理が速くなります。ただし、表、パーティションまたは索引に対するNOLOGGING操作の後、バックアップを実行する前にメディア障害が発生すると、変更されたすべての表、パーティションおよび索引が破損することがあります。

NOLOGGING句が使用されている場合、ダイレクト・パスINSERT操作(ディクショナリ更新以外)では、REDOログは常に生成されません。NOLOGGING属性はUNDOには影響せず、REDOのみに影響します。正確には、NOLOGGINGを使用すると、ダイレクト・パスINSERT操作ではごくわずかのREDO(フル・イメージREDOとは逆のレンジ無効REDO)が生成されます。

下位互換性のため、CREATE TABLE文での代替キーワードとして[UN]RECOVERABLEも引き続きサポートされています。ただし、この代替キーワードは今後のリリースでサポートが終了する可能性があります。

表領域レベルでは、LOGGING句によって、その表領域に作成されるすべての表、索引およびパーティションのデフォルト・ロギング属性が指定されます。既存の表領域のロギング属性がALTER TABLESPACE文によって変更されると、ALTER文の後で作成されたすべての表、索引およびパーティションには新しいロギング属性が適用されます。既存の表、索引、パーティションのロギング属性は変化しません。表領域レベルのロギング属性は、表、索引またはパーティション・レベルの指定で上書きできます。

デフォルトのロギング属性はLOGGINGです。ただし、ALTER DATABASE NOARCHIVELOGを発行してデータベースをNOARCHIVELOGモードにした場合、ロギング属性の指定にかかわらず、ロギングなしで実行できるすべての操作ではログが生成されなくなります。

8.8.5 パラレルでの索引の作成によるパフォーマンスの最適化

パラレルで索引を作成してパフォーマンスを最適化できます。

複数のプロセスが同時に作動して、1つの索引を作成できます。索引を作成するために必要な処理を複数のサーバー・プロセスに分割することで、Oracle Databaseでは、1つのサーバー・プロセスによって索引をシリアルで作成した場合に比べて速く索引を作成できます。

パラレル索引作成では、ORDER BY句での表スキャンとほぼ同様の処理が行われます。表がランダムにサンプリングされ、索引をDOPと同数に均等に分割するための索引キーのセットが検出されます。問合せプロセスの第1セットが表をスキャンしてキーと行IDのペアを抽出し、問合せプロセスの第2セットのプロセスに対してキーに基づいて各ペアを送ります。第2セットの各プロセスは、キーをソートし、通常の方法で索引を構築します。索引のすべての部分が構築されると、パラレル実行コーディネータが各部(ソート済)を連結して、最終的に索引を形成します。

パラレルのローカル索引作成では、1つのサーバー・セットが使用されます。セットの各サーバー・プロセスは、割り当てられた表パーティションをスキャンし、そのパーティションに対して索引パーティションを構築します。所定のDOPに対して半数のサーバー・プロセスが使用されるため、パラレルのローカル索引作成が可能になるのはDOPが高い場合です。ただし、DOPは作成する索引パーティション数以内に制限されます。この制限を回避するには、DBMS_PCLXUTILパッケージを使用できます。

索引作成時にREDOおよびUNDOのロギングを行わないことをオプションで指定できます。こうすると、パフォーマンスが大きく向上する可能性がありますが、索引が一時的にリカバリ不可の状態になります。新しい索引のバックアップを取得すると、リカバリは可能になります。アプリケーションで、索引のリカバリ時に索引を再作成するNOLOGGING句の使用を検討してください。

CREATE INDEX文のPARALLEL句のみが、索引作成のDOPを指定するただ1つの方法です。DOPがCREATE INDEX文のPARALLEL句に指定されないと、CPUの数がDOPとして使用されます。PARALLEL句がない場合、索引作成はシリアルで行われます。

索引をパラレルで作成するとき、STORAGE句には、問合せサーバー・プロセスで作成される各副索引の記憶域を指定します。このため、INITIAL値が5MB、DOPが12で作成される索引は、索引作成時に少なくとも60MBの記憶域を消費します。各プロセスが5MBのエクステントで開始するためです。問合せコーディネータ・プロセスがソート済の副索引を結合するときに、エクステントの一部が切り捨てられ、生成される索引はリクエストの60MBよりも小さくなることがあります。

UNIQUEまたはPRIMARY KEY制約を表に追加するか、有効にすると、必要な索引をパラレルで自動的に作成できなくなります。かわりに、CREATE INDEX文と適切なPARALLEL句を使用して、必要な列に対して手動で索引を作成します。こうすることで、制約を有効にするか追加するときに、Oracle Databaseが既存の索引を使用します。

同じ表の複数の制約を同時にパラレルで有効にできるのは、すべての制約がすでにENABLE NOVALIDATE状態になっている場合です。次の例では、ALTER TABLE ENABLE CONSTRAINT文が、制約をパラレルでチェックする表スキャンを実行します。

CREATE TABLE a (a1 NUMBER CONSTRAINT ach CHECK (a1 > 0) ENABLE NOVALIDATE)
PARALLEL; 
INSERT INTO a values (1);
COMMIT;
ALTER TABLE a ENABLE CONSTRAINT ach;

8.8.6 パラレルDMLのヒント

このトピックでは、パラレルDML機能のヒントについて説明します。

内容は次のとおりです。

関連項目:

8.8.6.1 パラレルDMLのヒント1: INSERT

このトピックでは、SQL INSERT文を使用した場合のパラレルDMLについて説明します。

INSERT文を使用して実行できる機能は表8-5にまとめられます。

表8-5 INSERT機能のまとめ

挿入タイプ パラレル シリアル NOLOGGING

従来型

不可

パラレルDMLを有効にしてNOAPPENDヒントを使用して、従来型のパラレル挿入を実行する方法の詳細は、この項の説明を参照してください。

不可

ダイレクト・パス

INSERT

(APPEND)

可能(次の指定が必要)

PARALLEL DMLモードを有効にするためのALTER SESSION ENABLE PARALLEL DMLまたはENABLE_PARALLEL_DML SQLヒント

さらに、次のいずれか1つの指定

  • 並列処理を明示的に設定する表のPARALLEL属性またはPARALLELヒント

  • モードを明示的に設定するAPPENDヒント

または次の指定

強制的にPARALLEL DMLモードにするALTER SESSION FORCE PARALLEL DML

可能(次の指定が必要):

APPENDヒント

可能(次の指定が必要):

パーティションまたは表に対するNOLOGGING属性の設定

パラレルDMLが有効で、PARALLELヒントがあるか PARALLEL属性がデータ・ディクショナリの表に設定されている場合、制限が適用されないかぎり挿入操作はパラレルで行われ追加されます。PARALLELヒントまたはPARALLEL属性のいずれかがない場合、挿入操作はシリアルで行われます。自動DOPでは、パラレルDMLが有効化または強制される場合にかぎり、SQL文のDML部分のみがパラレル化されます。

パラレルDMLが有効化される場合は、NOAPPENDヒントを使用してパラレルの従来型挿入操作を実行できます。たとえば、/*+ noappend parallel */をSQL INSERT文で使用して、パラレルの従来型挿入を実行できます。

SQL> INSERT /*+ NOAPPEND PARALLEL */ INTO sales_hist SELECT * FROM sales;

パラレルの従来型挿入操作の利点は、ダイレクト・パスINSERTの制約なしにオンライン操作を実行できることです。パラレルの従来型挿入操作のデメリットは、ダイレクト・パスINSERTよりもプロセスの速度が遅いことです。

8.8.6.2 パラレルDMLのヒント2: ダイレクト・パスINSERT

このトピックでは、ダイレクト・パスINSERT操作を使用した場合のパラレルDMLについて説明します。

追加モードは、パラレルの挿入操作時のデフォルトです。データは、表に割り当てられる新規ブロックに常に挿入されます。APPENDヒントの使用はオプションです。追加モードは、INSERT操作の速度を速める場合には使用しますが、領域の使用率の最適化が必要な場合は使用しないでください。NOAPPENDを使用すると追加モードを上書きできます。

APPENDヒントは、シリアルとパラレルの両方の挿入操作に適用されます。このヒントを使用すると、シリアル挿入もより高速になります。ただし、APPENDは多くの領域を使用する必要があり、ロックのオーバーヘッドも増加します。

NOLOGGINGAPPENDを一緒に使用すると、プロセスはさらに速くなります。NOLOGGINGは操作のREDOログが生成されないことを意味します。NOLOGGINGはデフォルトではありません。パフォーマンスを最適化するときに使用します。表またはパーティションのリカバリが必要となる通常の場合には使用しないでください。リカバリが必要な場合は、操作の直後にバックアップを取得するようにします。ALTER TABLE [NO]LOGGING文を使用して、適切な値を設定します。

8.8.6.3 パラレルDMLのヒント3: INSERT、MERGE、UPDATEおよびDELETEのパラレル化

このトピックでは、挿入、マージ、更新および削除操作を使用した場合のパラレルDMLについて説明します。

データ・ディクショナリで表またはパーティションにPARALLEL属性があるとき、この属性設定が、INSERT文、UPDATE文、DELETE文および問合せでの並列処理を決定するために使用されます。文での表に対する明示的なPARALLELヒントは、データ・ディクショナリのPARALLEL属性の効果よりも優先されます。

NO_PARALLELヒントを使用すると、データ・ディクショナリの表のPARALLEL属性を上書きできます。一般的にヒントは属性よりも優先されます。

DML操作の並列処理が考慮されるのは、ALTER SESSION ENABLE PARALLEL DML文を使用してセッションがPARALLEL DMLモードになっている場合、または、ENABLE_PARALLEL_DMLヒントを使用して特定のSQL文がPARALLEL DMLモードになっている場合です。このモードは、問合せまたはDML文の問合せ部分の並列処理には影響しません。

8.8.6.3.1 INSERT SELECTのパラレル化

INSERT ... SELECT文では、INSERTキーワードの後にPARALLELヒントを指定できます。このヒントはSELECTキーワードの後にも指定できます。

INSERTキーワードの後のPARALLELヒントはINSERT操作のみに適用され、SELECTキーワードの後のPARALLELヒントはSELECT操作のみに適用されます。したがって、INSERT操作とSELECT操作の並列処理は互いに独立しています。一方の操作をパラレルで実行できなくても、もう一方の操作をパラレルで実行できるかどうかには影響しません。

ユーザーがパラレルDMLをセッションで明示的に有効化した場合、および関連する表にデータ・ディクショナリ・エントリでPARALLEL属性が設定されている場合、挿入操作をパラレル化できる機能により既存の動作が変更されます。この場合、選択操作がパラレル化された既存のINSERT SELECT文で、挿入操作もパラレル化できます。

複数の表を問い合せる場合は、複数のSELECT PARALLELヒントと複数のPARALLEL属性を指定できます。

例8-5に、ACMEの買収後に雇用された新しい従業員の追加を示します。

例8-5INSERT SELECTのパラレル化

INSERT /*+ PARALLEL(employees) */ INTO employees
SELECT /*+ PARALLEL(ACME_EMP) */ *  FROM ACME_EMP;

この例ではAPPENDキーワードは必要ありません。PARALLELヒントによって追加が暗黙的に指定されるためです。

8.8.6.3.2 UPDATEとDELETEのパラレル化

PARALLELヒント(UPDATEまたはDELETEキーワードの直後に指定)は、基礎となるスキャン操作に適用されるだけではなく、UPDATEまたはDELETE操作にも適用されます。

または、変更対象の表の定義に指定されるPARALLEL句で、UPDATEまたはDELETEのパラレル化を指定できます。

セッションまたはトランザクションについてパラレルDMLを明示的に有効化した場合、問合せ操作がパラレル化されたUPDATE文またはDELETE文は、UPDATE操作またはDELETE操作もパラレル化できます。文の副問合せまたは更新可能ビューには、独自のPARALLELヒントまたは句を指定できますが、これらのパラレル・ディレクティブは更新または削除をパラレル化する決定には影響しません。これらの操作をパラレルで実行できなくても、UPDATEまたはDELETE部分をパラレルで実行できるかどうかには影響しません。

例8-6に、ダラスのすべての店員を10%昇給する更新操作を示します。

例8-6UPDATEとDELETEのパラレル化

UPDATE /*+ PARALLEL(employees) */ employees
 SET salary=salary * 1.1 WHERE job_id='CLERK' AND department_id IN
  (SELECT department_id FROM DEPARTMENTS WHERE location_id = 'DALLAS');

PARALLELヒントは、UPDATE操作とスキャンに適用されます。

例8-7には、カテゴリ39のすべての商品の削除を示します。最近、事業が別会社として分離されたためです。

例8-7UPDATEとDELETEのパラレル化

DELETE /*+ PARALLEL(PRODUCTS) */ FROM PRODUCTS 
  WHERE category_id = 39;

ここでも、並列性処理、表employeesのスキャンとUPDATE操作に適用されます。

8.8.7 パラレルでの増分データ・ロード

パラレルDMLを更新可能結合ビュー機能と組み合せると、データ・ウェアハウス・システムの表をリフレッシュするための効率のよいソリューションが得られます。

表をリフレッシュするには、OLTP本番システムで生成される差分データを使用して更新します。

次の例では、列c_keyc_nameおよびc_addrを含むcustomersという表をリフレッシュするとします。差分データには、新しい行またはデータ・ウェアハウスの最後のリフレッシュ以降に更新された行が含まれます。この例では、本番システムの更新データはデータ・ウェアハウス・システムにASCIIファイルとして送られます。リフレッシュ・プロセスを開始する前に、これらのファイルを一時表diff_customerにロードする必要があります。このタスクを効率よく実行するには、パラレル・オプションとダイレクト・オプションの両方を指定したSQL*Loaderを使用できます。パラレルでロードする場合はAPPENDヒントも使用します。

diff_customerがロードされたら、リフレッシュ・プロセスを開始できます。これは、次に示すように、2フェーズで実行するか、パラレルでのマージにより実行することができます。

8.8.7.1 パラレルでの表の更新のためのパフォーマンスの最適化

このトピックでは、パラレルでの表の更新のためのパフォーマンスの最適化方法について説明します。

次の文は、副問合せを使用して更新する単純なSQLの実装です。

UPDATE customers SET(c_name, c_addr) = (SELECT c_name, c_addr
  FROM diff_customer WHERE diff_customer.c_key = customer.c_key)
  WHERE c_key IN(SELECT c_key FROM diff_customer);

残念ながら、この文の2つの副問合せはパフォーマンスに影響します。

かわりに、更新可能結合ビューを使用してこの問合せを作成しなおすことができます。問合せを再作成するには、まず主キー制約をdiff_customer表に追加して、変更される列がキー保存表にマップされるようにします。

CREATE UNIQUE INDEX diff_pkey_ind ON diff_customer(c_key) PARALLEL NOLOGGING;

ALTER TABLE diff_customer ADD PRIMARY KEY (c_key);

その後、次のSQL文を使用してcustomers表を更新できます。

UPDATE /*+ PARALLEL(cust_joinview) */
  (SELECT /*+ PARALLEL(customers) PARALLEL(diff_customer) */
  CUSTOMER.c_name AS c_name CUSTOMER.c_addr AS c_addr,
   diff_customer.c_name AS c_newname, diff_customer.c_addr AS c_newaddr
   FROM diff_customer
   WHERE customers.c_key = diff_customer.c_key) cust_joinview
   SET c_name = c_newname, c_addr = c_newaddr;

結合ビューcust_joinviewにデータを提供するための基本スキャンはパラレルで実行されます。その後、更新をパラレル化して、さらにパフォーマンスを向上させることができます。ただし、これはcustomers表がパーティション化されている場合のみです。

8.8.7.2 パラレルでの表への新しい行の効率的な挿入

このトピックでは、パラレルでの表への新しい行の効率的な挿入方法について説明します。

リフレッシュ・プロセスの後半のフェーズでは、diff_customer一時表の新しい行をcustomers表に挿入します。更新の場合とは異なり、INSERT文の副問合せの指定は必要です。

INSERT /*+PARALLEL(customers)*/ INTO customers SELECT * FROM diff_customer s);

ただし、HASH_AJヒントを使用すると、この副問合せは必ずアンチハッシュ結合に変換されます。こうすると、パラレルINSERTを使用して、前の文を効率よく実行できます。パラレルINSERTは、表がパーティション化されていなくても適用できます。

8.8.7.3 パラレルでのマージによるパフォーマンスの最適化

このトピックでは、パラレルでのマージによるパフォーマンス最適化方法について説明します。

次の例に示すように、更新と挿入を組み合せて1つの文にすることができます。これは一般的にはマージと呼ばれます。

MERGE INTO customers USING diff_customer
ON (diff_customer.c_key = customer.c_key) WHEN MATCHED THEN
  UPDATE SET (c_name, c_addr) = (SELECT c_name, c_addr 
  FROM diff_customer WHERE diff_customer.c_key = customers.c_key) 
WHEN NOT MATCHED THEN
 INSERT VALUES (diff_customer.c_key,diff_customer.c_data);

前述の例のSQL文では、「パラレルでの表の更新のためのパフォーマンスの最適化」および「パラレルでの表への新しい行の効率的な挿入」のすべての文と同じ結果をアーカイブします。