4

iBatis を使用して、1 つのテーブル (SQL Server 2005) に 20,000 行を挿入する必要があります。それを行う最速の方法は何ですか? 私はすでにバッチモードを使用していますが、あまり役に立ちませんでした:

try {
  sqlMap.startTransaction();
  sqlMap.startBatch();
  // ... execute statements in between
  sqlMap.commitTransaction();
} finally {
  sqlMap.endTransaction();
}
4

4 に答える 4

4

他の人が言及しているバルクローダーを除いて、SQL を使用してそれを行う最善の方法を考えてみましょう。(また、混在したデータを異なるテーブルに送信している場合、バルク ローダーはうまく機能しません。)

まず、使用している抽象化レイヤー (この場合は iBatis) を使用するべきではありません。効果的にほとんど価値を提供しないためですが、その抽象化レイヤーには CPU コストがいくらか (必ずしも多くはありませんが、いくらか) かかります。生のデータベース接続を使用する必要があります。

次に、混乱した INSERT ステートメントを送信します。問題は、ステートメントに単純な文字列 (つまり、INSERT INTO TABLE1 VALUES('x','y', 12)) と準備済みステートメント (INSERT INTO TABLE1 VALUES(?, ?, ?)) を使用する必要があるかどうかです。

これは、データベースと DB ドライバーによって異なります。

単純な文字列を使用する際の問題は、基本的に内部形式 (Java データを挿入すると仮定) から文字列への変換コストです。数値または日付を文字列に変換することは、実際にはかなり高価な CPU 操作です。一部のデータベースとドライバーは、単なる文字列データではなく、バイナリ データを直接処理します。したがって、その場合、PreparedStatement は、データを変換する必要がない可能性があるため、CPU をいくらか節約できます。

欠点は、この要因が DB ベンダーによって異なり、場合によっては JDBC ベンダーによっても異なることです。たとえば、Postgres (私は信じています) は、バイナリではなく SQL 文字列でのみ機能するため、PreparedStatement を使用することは、単純に自分で文字列を作成するよりも無駄です。

次に、ステートメント タイプを取得したら、JDBC Statement クラスのaddBatch () メソッドを使用します。addBatch が行うことは、SQL ステートメントをバッチにグループ化することです。利点は、DB に複数のリクエストを送信する代わりに、単一の LARGE リクエストを送信することです。これにより、ネットワーク トラフィックが削減され、スループットが大幅に向上します。

詳細は、すべてのドライバー/データベースが addBatch をサポートしているわけではなく (少なくとも十分ではありません)、バッチのサイズも制限されていることです。ほとんどの場合、20,000 行すべてに対して addBatch を実行して、それが機能すると期待することはできませんが、それが最善の方法です。この制限も、データベースによって異なります。

Oracle の場合、以前は 64K のバッファを使用していました。基本的に、文字通りの INSERT ステートメントを受け取り、それらを 64K のバッチに蓄積するラッパー関数を作成しました。

したがって、JDBC を介して SQL 経由でデータを一括挿入したい場合は、これらがその方法です。大きな改善点はバッチ モードです。Statement と PreparedStatement は、CPU を節約する可能性が高く、ドライバーがバイナリ プロトコルをサポートしている場合はネットワーク トラフィックを節約する可能性があります。

十分に満足するまで、テスト、すすぎ、繰り返します。

于 2008-11-13T21:51:22.500 に答える
2

これはあなたの db サーバーに固有のものではありませんが、以前は行をローカル ファイルに csv 形式で書き込んでから、データベースにファイルをインポートさせることに成功しました。これは、挿入ステートメントやバッチ挿入よりもかなり高速でした。

于 2008-11-13T21:21:54.510 に答える
2

SQL Server では、バッチでレコードを挿入する高速な方法はBULK INSERTを使用することです。ただし、この方法では、アプリケーションから直接ではなく、テキスト ファイルからレコードが読み込まれます。

また、ファイルの作成に費やされた時間も考慮されていません。それが実際の挿入からの速度の増加を相殺する場合は、検討する必要がある場合があります. これが全体的に少し遅くなったとしても、データベース サーバーを拘束する時間が短くなることに注意してください。

他に試すことができる唯一のことは、バッチをまったく別のテーブル (インデックスなどなし) に挿入 (ステージング) することです。次に、レコードをそのステージング テーブルからターゲット テーブルに移動し、ステージング テーブルを削除します。これにより、最初にデータがサーバーに移動されるため、最終的な挿入はすべて SQL サーバー自体で行われます。繰り返しますが、これは 2 ステップのプロセスなので、両方のステップの時間をカウントする必要があります。

于 2008-11-13T21:23:58.780 に答える
1

一括挿入は、データベース独自の一括ローダー ツールを使用して行うのが最適です。たとえば、Oracle の場合は SQL*Loader です。多くの場合、これらは、これまでに作成したものよりも高速です。

于 2008-11-13T21:02:02.570 に答える