大量のレコードを挿入する必要があり、スループットが問題となる場合には、DBMS へのラウンドトリップを減らすことで解決できることがあります。概要については「データ更新のブロッキング」を参照してください。
大量のレコードを挿入する必要がある場合、レコードを 1 つずつ挿入するのではなくブロックで挿入するとパフォーマンスが大幅に向上します (「ブロック挿入のパフォーマンス」を参照してください)。パフォーマンスがどの程度向上するかは、行数およびブロックのサイズによって異なります。
New 構文は、次に示す「Blocking NumericExpression」のオプション節に対応しています。この節があると、ブロック (バッチ) 挿入メカニズムが有効となり、ブロックごとのレコードの数をコントロールします。「New コマンド」で、完全な構文を参照してください。
New [ Blocking <数値式> ] ....
[ When Duplicate ] ....EndNew
ここで <数値式> は 1 ~ 2,147,483,647 の数値を返すエクスプレッションです。
for each
...
new blocking 100
Att1 = ...
Att2 = ...
when duplicate
Att2 = ...
endnew
endfor
実際の挿入は、各ブロックの最後に実行されます。New コマンドにはブロッキング因数 N があり、繰り返し構造 (例: For Each コマンド) の中にあるとします。For Each コマンド (およびその中にある New コマンド) の本文が実行されるたびに新しいレコードが挿入されることはなく、サイズ N のメモリーブロック (バッファー) に追加されます。その後バッファーがいっぱいになると、ブロック全体を挿入するため、特別な (多数行の) 挿入がデータベースに送信されます。追加される N レコードの一部が重複していることが判明した場合、特別な挿入は失敗となります。次に示す単純な挿入コマンドを使用して、N ブロックの全レコードの挿入が 1 件ずつ行われます。
注: 最後のブロック (N レコード未満を含む) は次のように挿入されます:
ブロックの保存が有効になっている場合、グループについて生成されたコードは次のようになります:
Add record to block
NumberOfRecords += 1
if NumberOfRecords >= NumericExpression
Insert Record Block //一括挿入コマンド
When Duplicate //レコード挿入に失敗
/* ブロック内の全レコードをスキャンして重複の有無を確認 */
For each record in block
Insert Record //単純な挿入コマンド
When Duplicate
/* 重複する場合のユーザーコード */
endwhenduplicate
endfor
endwhenduplicate
NumberOfRecords = 0
endif
重複キーエラーの場合、コードはブロックのレコードを 1 つずつ挿入しようとし、重複キーを生成するレコードに対して When Duplicate コードを実行してブロックのレコードを一掃します。Rollback コマンドが実行された場合、トランザクションのロールバックが実行され、挿入準備の完了しているブロック (バッファー) 内のレコードがすべて削除されます。
この節は次のプラットフォームではサポートされません:
- Java - DB2 UDB
- .NET - MySQL
- .NET - Informix
- .NET - PostgreSQL
- .NET Core - PostgreSQL
注:
GeneXus 17 では、Blocking 節がプラットフォームでサポートされない場合、次のような内容のメッセージがスローされます: spc0222 %1% の Blocking 節は現時点で行 %2% から始まるグループでサポートされていません。
ロジックや When Duplicate コードの頻度などによって異なります。挿入直後にそのレコードにアクセスする必要がある場合は、ブロック挿入を使用することはできません。重複するレコードが多い場合は、通常はブロック挿入を使用しないほうが良いでしょう。
ブロックごとのレコード数は場合によって異なります。決められた数はありません。
実行時にブロックごとのレコード数を変更するとどうなりますか?
NumericExpression が変数のエクスプレッションである場合、その値は各ブロックの最初の挿入時にのみ指定できます。
When Duplicate コードは Return 直前まで実行されます。プログラムの残りに対しては実行されません (When Duplicate コードは、カーソルバッチのバッファーが完了した場合または Commit コマンドが実行された場合に呼び出される新しいルーチンにおいて生成されます)。
どちらの場合も、対応する呼び出しが行われます。
グループの範囲内で Commit コマンドを実行すると、保留中の更新/削除がすべてサーバーに送信されます。つまり、レコードを処理するたびに Commit コマンドを発行しないでください。ブロッキングはパフォーマンスには影響しません。
Rollback コマンドが実行されると、トランザクションのロールバックが実行され、最後のコミット後に挿入されたレコードがすべて削除されます。完了したブロック、挿入されたブロック、または完了していないブロックに対応するレコードはすべて削除されます。
|