web-dev-qa-db-ja.com

百万の挿入:SqlBulkCopyタイムアウト

すべての接続文字列(db2OracleMSServer)を処理する実行中のシステムがすでにあります。

現在、いくつかの挿入を行うためにExecuteNonQuery()を使用しています。

SqlBulkCopy()の代わりにExecuteNonQuery()を使用して、パフォーマンスを向上させたいと考えています。 5,000万件を超えるレコードを持つクライアントがいます。

システムが複数のデータベースをサポートしているため、[〜#〜] ssis [〜#〜]は使用しません。

SqlBulkCopy()のパフォーマンスをテストするためのサンプルプロジェクトを作成しました。 MSServerの簡単な読み取りおよび挿入関数を作成しました

これが小さな関数です:

public void insertIntoSQLServer()
{
    using (SqlConnection SourceConnection = new SqlConnection(_sourceConnectionString))
    {
        //Open the connection to get the data from the source table
        SourceConnection.Open();
        using (SqlCommand command = new SqlCommand("select * from " + _sourceSchemaName + "." + _sourceTableName + ";", SourceConnection))
        {
            //Read from the source table
            command.CommandTimeout = 2400;
            SqlDataReader reader = command.ExecuteReader();

            using (SqlConnection DestinationConnection = new SqlConnection(_destinationConnectionString))
            {
                DestinationConnection.Open();
                //Clean the destination table
                new SqlCommand("delete from " + _destinationSchemaName + "." + _destinationTableName + ";", DestinationConnection).ExecuteNonQuery();

                using (SqlBulkCopy bc = new SqlBulkCopy(DestinationConnection))
                {
                    bc.DestinationTableName = string.Format("[{0}].[{1}]", _destinationSchemaName, _destinationTableName);
                    bc.NotifyAfter = 10000;
                    //bc.SqlRowsCopied += bc_SqlRowsCopied;
                    bc.WriteToServer(reader);
                }
            }
        }
    }
}

ダミーテーブルの数が200000未満の場合、バルクコピーは正常に機能しています。しかし、200 000レコードを超えると、次のエラーが発生します。

  • 保留中の操作があるオブジェクトで一括コピーを呼び出そうとしました。

OR

  • 待機操作がタイムアウトしました(IDataReaderの場合)

リーダーのCommandTimeoutを増やしました。 IDataReaderに関連するタイムアウトの問題が解決されたようです。

コードで何か問題がありますか?

14
billybob

WriteToServerを呼び出す前に、以下を追加してみてください...

bc.BatchSize = 10000;
bc.BulkCopyTimeout = 0;

デフォルトのバッチサイズまたはタイムアウトが何であるかはわかりませんが、これが問題である可能性があります。お役に立てば幸いです

また、最適なパフォーマンスを得るために、さまざまなバッチサイズで遊んでみることができます。

16
Spock

あなたはこれを試すことができます

bc.BatchSize = 100000; // How many Rows you want to insert at a time
bc.BulkCopyTimeout = 60; // Time in Seconds. If you want infinite waiting Time then assign 0.
2
Deepesh