一括コピー バッチ サイズの管理
一括コピー操作でバッチを使用する主な目的は、トランザクションのスコープを定義することです。一括コピー関数では、バッチ サイズが設定されていないと、一括コピー全体を 1 つのトランザクションと見なします。バッチ サイズが設定されている場合、各バッチはそのバッチの終了時にコミットされるトランザクションで構成されます。
バッチ サイズを指定せずに一括コピーを実行し、エラーが発生した場合は、一括コピー全体がロールバックされます。実行時間が長い一括コピーの復旧には時間がかかることがあります。バッチ サイズを設定すると、各バッチが 1 つのトランザクションと見なされ、各バッチがコミットされます。エラーが発生した場合は、最後の未解決のバッチだけがロールバックされます。
バッチ サイズは、ロックのオーバーヘッドにも影響を与えることがあります。SQL Server に対して一括コピーを実行する場合は、bcp_control を使用して TABLOCK ヒントを指定すると、行ロックではなくテーブル ロックを取得できます。1 つのテーブル ロックを設定すると、一括コピー操作全体のオーバーヘッドを最小限に抑えることができます。TABLOCK を指定しないと各行がロックされるので、一括コピーの実行中にすべてのロックを保持するオーバーヘッドにより、パフォーマンスが低下することがあります。トランザクションの長さだけロックが保持されるので、バッチ サイズを指定すると、定期的にコミットが発生して、その時点で保持されているロックが解放されるため、この問題を解決できます。
大量の行を一括コピーする場合、1 つのバッチを構成する行数がパフォーマンスに大きな影響を与えることがあります。推奨バッチ サイズは、実行する一括コピーの種類によって異なります。
- SQL Server への一括コピーを行う場合は、TABLOCK 一括コピー ヒントを指定し、大きなバッチ サイズを設定します。
- TABLOCK を指定しない場合は、バッチ サイズを 1,000 行未満に制限します。
データ ファイルから一括コピー入力を行う場合、bcp_exec を呼び出す前に BCPBATCH オプションを指定して bcp_control を呼び出すことで、バッチ サイズを指定します。bcp_bind と bcp_sendrow を使用してプログラム変数から一括コピーを行う場合、bcp_sendrow を x 回呼び出した後で bcp_batch を呼び出すことで、バッチ サイズを制御します。ここでの x は 1 つのバッチ内の行数です。
バッチはトランザクションのサイズを指定するだけでなく、ネットワーク経由でサーバーに行を送信するときにも影響を与えます。一括コピー関数では、通常、ネットワーク パケットがいっぱいになるまで bcp_sendrow からの行をキャッシュし、いっぱいになったパケットをサーバーに送信します。ただし、アプリケーションから bcp_batch を呼び出すと、パケットがいっぱいになったかどうかにかかわらず、現在のパケットがサーバーに送信されます。バッチ サイズを非常に小さくすると、いっぱいになっていないパケットが大量にサーバーに送信されるので、パフォーマンスが低下することがあります。たとえば、bcp_sendrow を呼び出すたびに bcp_batch を呼び出すと、各行が個別のパケットで送信されるので、行が非常に大きい場合を除き、各パケット内の領域が無駄になります。SQL Server のネットワーク パケットの既定のサイズは 4 KB ですが、アプリケーションから SQL_ATTR_PACKET_SIZE 属性を指定して SQLSetConnectAttr を呼び出すことで、このサイズを変更できます。
バッチのもう 1 つの副作用は、bcp_batch によって各バッチが完了されるまで、各バッチが未解決の結果セットと見なされることです。バッチが未解決の間に接続ハンドルで他の操作が試行されると、SQL Native Client ODBC ドライバでは、SQLState = "HY000" のエラーが発生し、次のエラー メッセージ文字列が表示されます。
"[Microsoft][SQL Native Client] Connection is busy with
results for another hstmt."