3

次のように、挿入するときにバッチステートメントを使用します。

BatchBindStep batch = create.batch(create
   .insertInto(PERSON, ID, NAME)
   .values((Integer) null, null));

for (Person p : peopleToInsert) {
  batch.bind(p.getId(), p.getName());
}
batch.execute();

これは、過去に数千のオブジェクトを挿入するときにうまく機能しました。ただし、いくつかの疑問が生じます。

  1. .bind()バッチの呼び出し回数に上限はありますか?
  2. もしそうなら、制限は何に依存していますか?
  3. .bind()を実行した後に再度呼び出すことは可能のよう.execute()です。.execute()以前にバインドされた値をクリアしますか?

最後の質問を明確にするために: 次のコードが実行された後...

BatchBindStep batch = create.batch(create
   .insertInto(PERSON, ID, NAME)
   .values((Integer) null, null));

batch.bind(1, "A");
batch.bind(2, "B");
batch.extecute();
batch.bind(3, "C");
batch.bind(4, "D");
batch.execute();

どの結果を期待する必要がありますか?

a)        b)
ID NAME   ID NAME
-------   -------
 1 A       1 A
 2 B       2 B
 3 C       1 A
 4 D       2 B
           3 C
           4 D

残念ながら、Javadocドキュメントも、この特定の使用パターンについて説明していません。

(この特定の質問をしている理由.execute()は、上記の制限を回避するために 1000 回のバインドごとに行う場合、複数の呼び出しでbatchオブジェクトを再利用できるかどうかを知る必要があるためです。).execute()

4

1 に答える 1

1

この回答は jOOQ 3.7 の時点で有効です

  1. バッチの .bind() 呼び出しの数に上限はありますか?

jOOQ にはありませんが、JDBC ドライバー/データベース サーバーにはそのような制限がある場合があります。

  1. もしそうなら、制限は何に依存していますか?

いくつかのこと:

  • jOOQ は、バインドされたすべての変数の中間バッファーを保持し、それらを一度に JDBC バッチ ステートメントにバインドします。そのため、クライアントのメモリによっても上限が課される場合があります。しかし、jOOQ 自体には制限がありません。
  • JDBC ドライバーがそのような制限を認識している可能性があります ( jOOQ が非バッチ ステートメントで制限を処理する方法については、この記事も参照してください)。既知の制限は次のとおりです。

    • SQLite: ステートメントごとに 999 個のバインド変数
    • Ingres 10.1.0: ステートメントごとに 1024 個のバインド変数
    • Sybase ASE 15.5: ステートメントごとに 2000 個のバインド変数
    • SQL Server 2008: ステートメントごとに 2100 個のバインド変数

    Oracle にそのような制限があることは知りませんが、おそらくあるでしょう。

  • 大量のデータを挿入するときに調整する必要があるのは、バッチ サイズだけではありません。もあります:

    • 一括サイズ、つまりステートメントごとに挿入される行数
    • バッチサイズ、つまりサーバーに送信されるバッチごとのステートメントの数
    • コミット サイズ、つまり、1 つのトランザクションでコミットされるバッチの数

    挿入の調整は、上記のすべての調整に要約されます。jOOQ には、上記のすべてを調整できる専用のインポート API が付属しています: http://www.jooq.org/doc/latest/manual/sql-execution/importing

  • ローダー テーブルへの挿入に SQL をバイパスすることも検討する必要があります。たとえば、Oracle の SQL*Loaderを使用します。すべてのデータを挿入したら、JDBC のバッチ ステートメントの PL/SQL バージョンであるPL/SQL のFORALLステートメントを使用して、データを「実際のテーブル」に移動できます。このアプローチは、JDBC で行うすべてのことよりも優れています。

  1. .execute() を実行した後、再度 .bind() を呼び出すことができるようです。.execute() は以前にバインドされた値をクリアしますか?

現在、execute()バインド値はクリアされません。代わりに、新しいステートメントを作成する必要があります。将来の jOOQ バージョンでは API 設計の不変性が優先されるため、これが変更される可能性はほとんどありません。

于 2016-03-11T09:56:15.263 に答える