7

私は巨大なテーブル (30 億行) を持っていますが、残念ながら期限切れのデータがほとんど含まれています。これらの期限切れの行をすべて削除し、残りを保持したいだけです。

次のようなステートメントを実行できます。

delete from giganticTable where exp_date < getDate()

実行計画では、約 4 億行が削除されると推定されています。

実行すると、これは 1 時間経っても終了しないだけでなく、データベース トランザクション ログ ファイルも 6 GB から 90 GB に増加します。これが発生している間、データベースは一括ログ復旧モデルであったことに注意してください。これを行うためのより良い方法があるに違いないと確信しているため、最終的にこのクエリをキャンセルしました。

同様の操作を実行する必要があるテーブルがいくつかあります。これらの行を復元したくない場合に、これらの行を削除する最も速くてスペース効率の良い方法は何ですか?

Microsoft SQL Server 2005 を使用していることに注意してください。

4

3 に答える 3

9

多数の行を含むテーブルから削除を実行して、たとえば5000程度のバッチで行を削除する場合に便利です(通常、どの値が最も速く機能するかをテストします。5000行、場合によっては10,000行など)。 。これにより、1つのステートメントが4億レコードをノックアウトするのを長時間待つのではなく、各削除操作をすばやく完了することができます。

SQL Server 2005では、次のようなものが機能するはずです(もちろん、最初にテストしてください)。

WHILE EXISTS ( SELECT * FROM giganticTable WHERE exp_date < getDate())
BEGIN
  DELETE TOP(5000) FROM giganticTable WHERE exp_date < getDate()
END

バッチで削除すると、ログファイルのサイズがどうなるかがわかります。それでもログが大量に発生する場合は、リカバリモデルをシンプルに変更し、レコードを削除してから、バルクログに切り替えてみてください。ただし、システムが最近のデータの損失を許容できる場合に限ります。その手順を試みる前に、私は間違いなく完全バックアップを作成します。このスレッドは、切り捨てのみを指定してログをバックアップするジョブを設定できることも示唆しているため、これは別のオプションになる可能性があります。テストできるインスタンスがあるといいのですが、バッチ削除から始めて、パフォーマンスとログファイルサイズにどのように影響するかを確認します。

于 2011-05-08T04:32:25.307 に答える
3

テーブルで多くの作業を行いたい場合、ログをオフにするなどのばかげたことを試してはいけません。長時間の作業中に問題が発生すると、データベースの破損やその他の問題が簡単に発生する可能性があるためです。ただし、問題を回避する方法があります。

実際のテーブルのスキーマと一致する一時テーブルを作成します。保持したいデータを入力します。次に、元のテーブルを切り捨てます (ログ ファイルに対して非常に高速で簡単です)。最後に、データを一時テーブルから元の (現在は空の) テーブルに移動します。

自動インクリメント主キーを使用する場合は、フィールドが元のキーを取得するように強制する必要があります (後で問題が発生しないようにするため)。

于 2011-05-08T04:00:00.520 に答える
1

毎日やるべきだったので、一度にそんなに大きな仕事をすることはありません。
あなたがそのような状況にあるので、ここに私の提案があります:

  1. rsbarroが言うように仕事を分割してください。while ステートメントはおそらく必要ありません。数日で実行できます。
  2. 次のように日付を明示的に記述します。

    delete from giganticTable where exp_date < '2013-08-07'
    
  3. 巨大なログについてはよくわかりません。本当に良い方法がないようです。
于 2013-08-07T06:23:55.007 に答える