SQL Serverの削除速度を改善する


12

巨大な本番データベースがあり、そのサイズは約300GBです。削除クエリのパフォーマンスを向上させる方法はありますか?現在、削除速度は1分あたり1〜10kですが、非常に低速です。


2
1分あたり1000行は非常に遅いように聞こえます。ブロッキングが発生していますか?または、行の選択も遅いので、インデックスの必要性が示唆されますか?
James Z

おそらく、削除基準をカバーするインデックスを作成する必要があります。
ギンデン2015年

6
答えを提供するのに十分な詳細がありません。どのクエリを実行しますか?関連する基準列(存在する場合)に索引がありますか?削除のトリガーはありますか?...
セバスチャンセヴリン

3
一度に10億行を削除しようとしていますか?自動拡張後の自動拡張を待っている可能性はありますか?(実際の削除アクティビティではなく、待機しているログアクティビティである可能性が高くなります。)この記事を参照してください ...
アーロンバートランド

3
また。外部キーの制約はありますか?完全なテーブル定義、クエリ、および実行計画を提供してください。
マーティン・スミス

回答:


20

1つのステートメントで多数の行を削除しようとしている場合は、ログアクティビティを待機している可能性があります。だからあなたはできる:

  1. ログが適切なサイズであることを確認して、成長イベントによって速度が低下しないようにします。デフォルトでは、ログはおそらく1MBから始まり、10%増加します。成長イベントは負荷が高く、10 GBの削除をログに記録している場合、これは現在だけでなく将来的にパフォーマンスを破壊します(これはVLFに対して何をするかによります)。
  2. テーブル全体を削除する場合は、/ TRUNCATEまたはを使用します。DROPCREATE
  3. テーブルのほとんどを削除する場合は、を使用SELECT INTOして、保持したいデータを別のテーブルに入れてからTRUNCATE、その小さな部分を元に戻します。(または単に古いテーブルを削除し、新しい名前を変更して、制約/権限を再適用するなど)
  4. 一度にすべてのデータを削除するのではなく、チャンクでデータを削除することにより、最初にログ記録の影響を最小限に抑えます。この記事を参照してください。また、一時的に単純復旧に切り替えることを検討することもできます。これCHECKPOINTにより、ログバックアップを取得する代わりにログを消去するだけで済みますが、ログを元に戻し、新しい完全バックアップを取得してログチェーンを再開する必要があります。 。

+1、私からの優れた記事。これにより、過去の開発者がログファイルの速度と成長のために私たちに連絡を取り続けるときに削除操作を理解できるようになりました。
KASQLDBA 2015年

また、不要なインデックスがある場合、それらを削除すると削除速度が向上します。繰り返しになりますが、すべてまたはほとんどすべてのデータを削除する場合は、最初にすべてのインデックスを削除し、その後それらを再度作成すると、良い影響を与える可能性があります。
Tony Hinkle、2015年

3
@Tonyによるインデックスの削除も(作成時と同様に)ログに記録する必要があるため、そのコストをいつ支払うかが問題になる場合があります。テストを行わなければ、後で保持する予定のないインデックスがない限り、(挿入/更新の場合と同様に)削除シナリオに大きな利点があるとは思いません。
アーロンバートランド

FK制約を一時的に無効にすると、クエリを改善できますか?
レフZ

3

ヒントはいくつかありますが、どのバージョンを使用していますか?エンタープライズ版ですか?とにかく:

  1. 可能であれば、トランザクションログをより高速なディスクに移動します
  2. 分析どこを。インデックスを使用して、削除するレコードを識別しますか?そうでない場合、インデックスを追加できますか?
  3. ドロップできるテーブルのインデックスはありますか?はいの場合、それらをドロップします。
  4. このテーブルに対して外部キーはありますか?これらは本当にあなたの削除を遅くすることができます。
  5. エンタープライズエディションがあり、ボトルネックがディスクIOである場合、行レベルでの圧縮は、少しの助けになります(または、データによってはそうではありません)。
  6. テーブルを分割できますか?ローカルインデックスとパーティションの削除はより高速になる可能性があります。
  7. アクティビティモニターを介してボトルネックの場所を調査します。

詳細を追加してください。大きなデータベースで作業する場合、有効な答えは1つではありません。


0

それらをチャンクごとにチャンクで削除してみてください。おそらくループ内を削除し、それぞれが独自のトランザクションである反復を削除してから、各ループの反復の終わりにログをクリアします。

また、レコードを削除するためにチャンクの値として使用する番号を見つける必要があります。徹底的なテストが必要ですが、最初にUATでチャンクの値をテストできればより良いでしょう。

続行方法については、大きな削除操作をチャンクに分割することを参照してください


0

大きなテーブルに再帰的な外部キーがある場合、削除が遅くなる可能性があります。

その場合、適切な時間を見つけ、依存サービスを無効にし、再帰的な外部キーを無効にし、大量の削除を実行してから、外部キーを再度復元します。


これはまさに私のケースでした。それは無効contraintにビット危険だが、削除は500 /秒に1行/ seocndから行った
Jurion

0

いくつかのポイントを追加しています...

  1. 述語にインデックスがあるかどうかを確認し、統計も確認してください。
  2. 多数の行を削除していて、一時テーブルオプションも必要ない場合。tablockオプションのために行きます。
  3. 特に削除トリガーの後に、トリガーがあるかどうかを確認します。

さらにヘルプが必要な場合は、使用しているクエリ、テーブル情報、およびブロック情報を投稿してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.