パラレルDMLを更新可能結合ビュー機能と組み合せると、データ・ウェアハウス・システムの表をリフレッシュするための効率のよいソリューションが得られます。表をリフレッシュするには、OLTP本番システムで生成される差分データを使用して更新します。
次の例では、列c_key
、c_name
およびc_addr
を含むcustomers
という表をリフレッシュするとします。差分データには、新しい行またはデータ・ウェアハウスの最後のリフレッシュ以降に更新された行が含まれます。この例では、本番システムの更新データはデータ・ウェアハウス・システムにASCIIファイルとして送られます。リフレッシュ・プロセスを開始する前に、これらのファイルを一時表diff_customer
にロードする必要があります。このタスクを効率よく実行するには、パラレル・オプションとダイレクト・オプションの両方を指定したSQL*Loaderを使用できます。パラレルでロードする場合はAPPEND
ヒントも使用します。
diff_customer
がロードされたら、リフレッシュ・プロセスを開始できます。これは、次に示すように、2フェーズで実行するか、パラレルでのマージにより実行することができます。
次の文は、副問合せを使用して更新する単純な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
表がパーティション化されている場合のみです。
リフレッシュ・プロセスの後半のフェーズでは、diff_customer
一時表の新しい行をcustomers
表に挿入します。更新の場合とは異なり、INSERT
文の副問合せの指定は必要です。
INSERT /*+PARALLEL(customers)*/ INTO customers SELECT * FROM diff_customer s);
ただし、HASH_AJ
ヒントを使用すると、この副問合せは必ずアンチハッシュ結合に変換されます。こうすると、パラレルINSERT
を使用して、前の文を効率よく実行できます。パラレルINSERT
は、表がパーティション化されていなくても適用できます。
更新と挿入を組み合せて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);