33

30 列と 500,000 行のテーブルSalesがあるとします。テーブル内の 400,000 ( の場所) を削除したいと思います"toDelete='1'"

しかし、私にはいくつかの制約があります:

  • テーブルは「頻繁に」読み書きされ、長い「削除」に時間がかかり、テーブルを長時間ロックしたくありません
  • トランザクション ログをスキップする必要がありますが (a のようにTRUNCATE)、実行中に"DELETE ... WHERE..."(条件を設定する必要があります)、これを行う方法が見つかりませんでした...

変換するためのアドバイスは大歓迎です

DELETE FROM Sales WHERE toDelete='1'

よりパーティション化され、おそらくトランザクションログがないものに。

4

10 に答える 10

47

を呼び出すDELETE FROM TableNameと、1 つの大きなトランザクションで削除全体が実行されます。これは高価です。

バッチで行を削除する別のオプションを次に示します。

deleteMore:
DELETE TOP(10000) Sales WHERE toDelete='1'
IF @@ROWCOUNT != 0
    goto deleteMore
于 2012-06-27T15:55:40.627 に答える
11

必要なのはバッチ処理です。

While (select Count(*) from sales where toDelete =1) >0
BEGIN
Delete from sales where SalesID in
(select top 1000 salesId from sales where toDelete = 1)
END

もちろん、バッチに使用するのに最適な値を試すことができます。私はテーブルに応じて 500 ~ 50000 を使用しました。カスケード削除を使用する場合、削除する子レコードがあるため、必要な数はおそらく少なくなります。

于 2012-06-27T15:56:04.253 に答える
5

過去にこれを行う必要があった方法の 1 つは、n 個のレコードを削除するストアド プロシージャまたはスクリプトを使用することでした。完了するまで繰り返します。

DELETE TOP 1000 FROM Sales WHERE toDelete='1'
于 2012-06-27T15:52:32.310 に答える
3

ROWLOCKテーブル全体がロックされないように、ヒントを与えるようにしてください。ただし、大量の行を削除すると、ロックのエスカレーションが発生します。

また、列にクラスター化されていないフィルター処理されたインデックス (1 つの値のみ)があることを確認してください。toDelete可能であれば、varchar (または現在のもの) ではなくビット列にします。

DELETE FROM Sales WITH(ROWLOCK) WHERE toDelete='1'

最終的に、テーブルを反復処理してチャンクで削除することができます。

更新しました

while ループとチャンクの削除はここでは新しいピンクなので、私のバージョンも投入します (以前の回答と組み合わせて):

SET ROWCOUNT 100
DELETE FROM Sales WITH(ROWLOCK) WHERE toDelete='1'

WHILE @@rowcount > 0
BEGIN
  SET ROWCOUNT 100
  DELETE FROM Sales WITH(ROWLOCK) WHERE toDelete='1'  
END
于 2012-06-27T15:53:50.153 に答える
1

以下を使用して、約5,000万件のレコードを削除しました-

BEGIN TRANSACTION     
     DeleteOperation:
     DELETE TOP (BatchSize)
     FROM  [database_name].[database_schema].[database_table] 

     IF @@ROWCOUNT > 0
     GOTO DeleteOperation
COMMIT TRANSACTION

BatchSize < 5000を維持すると、リソースのコストが低くなることに注意してください。

于 2017-01-09T05:47:58.850 に答える