1

何百万ものレコードを含むテーブルを更新する必要があります。現在、更新するすべてのレコードの ID をリストに保存しています。クエリは、次のように実用的に生成されます。

string queryPart="";
foreach (int id in transactionsToUpdate.ToList())
{
    queryPart+="TransactionID="+id;
    queryPart+=" OR ";
}

queryPart += "1=0";
string query = @"UPDATE dbo.OutgoingQueue SET Status='C' WHERE "+queryPart;

現在、リストに 100,000 個の値があっても、2 つの問題が発生します。まず、上記のコードは実行に時間がかかります (クエリ形成部分)。次に、DB でクエリを実行すると、Timeout Expired 例外が発生します。私が望むものを達成するためのより良い方法はありますか?

UPDATE : クエリの作成に時間がかかるという最初の問題は、stringbuilder を使用することで解決されました。しかし、2 つ目の問題はまだ残っています。タイムアウトを増やすと、sql out of resource 例外が発生します。

4

7 に答える 7

2

これは、テーブル値パラメーターの理想的な使用例です。ここを参照してください: http://msdn.microsoft.com/en-us/library/bb675163.aspx

または、#temp テーブル (またはステージング テーブル) を作成し、それを埋めSqlBulkCopy(こちらを参照)、それJOINに対してUPDATE.

于 2013-07-09T15:03:56.240 に答える
0

問題を解決するために次のことを行うことができます。

  1. 速度の問題 これについて、transactionsToUpdate.ToList() このリストに含まれる項目を教えてください。データベースからこのリストを埋める場合は、 for loop を実行する必要がないように更新クエリを変更することをお勧めします。アプリケーションのパフォーマンスが向上します。次のクエリのようなことができます。毎回ループする必要はありません。現在のコードよりもはるかに高速に実行され、このクエリを使用するとタイムアウトの問題に直面することはないと思います。

    UPDATE dbo.OutgoingQueue 
    SET Status='C' 
    FROM dbo.OutgoingQueuE AS A
    INNER JOIN 
    (
    QUERY BY WHICH YOU FILL UP CURRENT LIST
    ) AS B ON A.TransactionID = B.ID
    
  2. タイムアウトの問題 SQL コマンドを実行するときに、コマンドのタイムアウトを設定できます。

    SqlCommand myCommand = new SqlCommand(); myCommand.CommandTimeout = 15;

于 2013-07-09T12:59:05.567 に答える
0

私がとるタック:

cmd.CommandText = "CREATE TABLE #Values( id  Int )";
cmd.ExecuteNonQuery();


foreach (int id in transactionsToUpdate.ToList())
{
    cmd.CommandText = "INSERT INTO #Values VALUES( " + id.ToString() + ");" 
    cmd.ExecuteNonQuery();
}

これで、100,000 の IF ではなく、SQL の自然なドメインであるこの TEMP テーブルに対して結合することで、値をテストできます。同じ数値セットに対して複数のテストを行う場合は、テーブルを読み込んだ後にテーブルにインデックスを付けることが理にかなっている場合があります。

于 2013-07-09T15:14:55.873 に答える
0

更新のサイズに関する答え:

更新するIDの値が小さい場合は、バッチステートメントを作成して単一のトランザクションで送信できます。

update dbo.outgoingqueue out set status = 'C' where out.transactionID = %1;
update dbo.outgoingqueue out set status = 'C' where out.transactionID = %2;
update dbo.outgoingqueue out set status = 'C' where out.transactionID = %3;
update dbo.outgoingqueue out set status = 'C' where out.transactionID = %4;
update dbo.outgoingqueue out set status = 'C' where out.transactionID = %5;
update dbo.outgoingqueue out set status = 'C' where out.transactionID = %6;

ID が小さすぎて単一のトランザクションで実行できない場合は、一時テーブルを作成して、次のような更新クエリを実行できます。

update dbo.outgoingqueue out set status = 'C' where 
 exists (select null from tmp_tab where tmp_tab.transactionID = out.transactionID);

すべてのレコードを更新する場合、最善の方法はまったく更新しないことです。

次を使用して、新しい名前で新しいテーブルを作成する必要があります。

select <column list> into <table name> from <source>;

次に、selectセットで新しい値を設定し、最後にテーブルの名前を変更します。

于 2013-07-09T14:49:25.377 に答える