3

一度に約 10 万件のレコードを更新する 1 つの更新クエリを実行することは可能ですか、またはまったく推奨されますか?

もしそうなら、どうすればそれを行うことができますか? ストアド プロシージャに配列を渡そうとしていますが、うまくいかないようです。これが私の SP です。

CREATE PROCEDURE [dbo].[UpdateAllClients]
    @ClientIDs varchar(max)
AS
BEGIN
    DECLARE @vSQL varchar(max)
    SET @vSQL = 'UPDATE Clients SET LastUpdate=GETDATE() WHERE ID IN (' + @ClientIDs + ')';
    EXEC(@vSQL);
END

何が機能していないのかわかりませんが、関連するクエリを更新していないだけです。

誰?

4

7 に答える 7

5

は、 (カンマ区切り値として)全体UPDATEを読み取っています。それをもっと説明するために、あなたはこのようにやっています。@ClientIDs

仮定します@ClientIDs = 1,2,3,4,5

あなたのUPDATEコマンドはこのように解釈しています

UPDATE Clients SET LastUpdate=GETDATE() WHERE ID IN ('1,2,3,4,5')';

ではない

UPDATE Clients SET LastUpdate=GETDATE() WHERE ID IN (1,2,3,4,5)';

あなたの質問に対する1つの提案は、あなたUPDATEの例でサブクエリを使用することです

UPDATE Clients 
   SET LastUpdate = GETDATE() 
WHERE ID IN
    (
       SELECT ID
       FROM tableName
       -- where condtion
    )

これが理にかなっていることを願っています。

お役に立てれば

于 2012-09-07T07:50:11.700 に答える
3

知っておくべきいくつかの注意事項。

このような大きな更新は、ターゲット テーブルをロックする可能性があります。操作によって 5000 行を超える行が影響を受ける場合、個々の行ロックがテーブル ロックに昇格し、他のプロセスがブロックされます。これがシナリオで問題を引き起こす可能性がある場合は、覚えておく価値があります。参照:ロックのエスカレーション

このように更新する行が多数ある場合、私が検討するアプローチは(基本)です:

  1. 100K ID をステージング テーブルに一括挿入します (たとえば、.NET からは SqlBulkCopy を使用します)。
  2. 上記のステージング テーブルへの結合を使用して、ターゲット テーブルを更新します。
  3. ステージング テーブルを削除する

これにより、プロセスを制御する余地が増えますが、ワークロードをチャンクに分割し、一度に x 行ずつ実行します。

于 2012-09-07T07:59:18.373 に答える
0

配列を指定する場合、'IN' に渡すアイテムの数には制限があります。

したがって、テーブル全体を更新するだけの場合は、IN 条件をスキップしてください。

ない場合は IN 内に SQL を指定してください。それは仕事をするべきです

于 2012-09-07T07:53:21.547 に答える
0

SQL ステートメントが長すぎるため、データベースはその SQL ステートメントを拒否する可能性が非常に高くなります。

非常に多くのレコードを一度に更新する必要がある場合、データベース スキーマが適切でない可能性があります。おそらく、LastUpdate データはクライアントごとに個別に保存するのではなく、グローバルに 1 回だけ、またはクライアントの一定のグループに対して 1 回だけ保存する必要がありますか?

しかし、全体像を見ずに適切な行動方針を推奨することは困難です。

于 2012-09-07T07:53:58.387 に答える
0

各 SQL ステートメント自体がtransactionステートメントです。これは、SQLサーバーがこれらの数百万行すべてのロックを取得しようとしていることを意味します。これは、テーブルのパフォーマンスを実際に低下させる可能性があります。したがって、パフォーマンスを損なう何百万行もあるテーブルを更新する傾向はありません。回避策は、DML 操作の前に行数を設定することです

set rowcount=100
UPDATE Clients SET LastUpdate=GETDATE()
WHERE ID IN ('1,2,3,4,5')';
set rowcount=0

またはSQLサーバー2008から、Topキーワードをパラメータ化できます

Declare @value int
set @value=100000 
again:
UPDATE top (@value) Clients SET LastUpdate=GETDATE()
WHERE ID IN ('1,2,3,4,5')';
if @@rowcount!=0  goto again 

上記のクエリの速度を確認し、変数の値を調整および変更します。上記の回答で示唆されているように、より小さな単位のタスクを分割する必要があります

于 2012-09-07T09:24:47.207 に答える
0

どのバージョンの SQL サーバーを使用していますか? 2005 年以降の場合は、TVP (テーブル値パラメーター - http://msdn.microsoft.com/en-us/library/bb510489.aspx ) を使用することをお勧めします。データの転送は (巨大な文字列を構築するのではなく) 高速になり、クエリは見栄えが良くなります。

update c
set lastupdate=getdate()
from clients c
join @mytvp t on c.Id = t.Id
于 2012-09-07T08:57:56.997 に答える