5

入力された日付に基づいて大規模な (〜 50m レコード DB) から行を削除するアーカイブ スクリプトを実行しています。日付フィールドは、テーブルのクラスター化インデックスであるため、条件ステートメントを適用しています。

この削除を while ループで実行し、バッチで 1000 から 100,000 のレコードを試しています。バッチサイズに関係なく、驚くほど遅いです。1 分間に 10,000 件のレコードが削除されます。実行計画を見ると、「Index Delete」に多くの時間が費やされています。テーブルには約 15 のフィールドがあり、そのうちの約 10 には何らかのインデックスがあります。この問題を回避する方法はありますか? 各インデックスの削除になぜそんなに時間がかかるのかさえわかりません。誰かがここで何が起こっているのかを正確に明らかにすることができますか? これは私の実行計画のサンプルです:

代替テキスト http://img94.imageshack.us/img94/1006/indexdelete.png

(シーケンスは削除コマンドを指します)

このデータベースはライブであり、頻繁に挿入されています。そのため、サイズをトリミングするためにコピーと切り捨ての方法を使用することをためらっています。ここで見逃している他のオプションはありますか?

4

5 に答える 5

6

クラスター化されたインデックスから 10,000 レコード + クラスター化されていない 5 つのレコードを削除するのに、1 分もかからないはずです。本当に遅い IO サブシステムを使用しているようです。値は次のとおりです。

  • 平均 ディスク秒/書き込み
  • 平均 ディスク秒/読み取り
  • 平均 ディスク書き込みキューの長さ
  • 平均 ディスク読み取りキューの長さ

操作に関係する各ドライブ (ログのものを含む!)。インデックスを個別のファイル グループに配置し、各ファイル グループを独自の LUN または独自のディスクに割り当てた場合、より問題のあるインデックスを特定できます。また、ログのフラッシュが大きなボトルネックになる可能性があります。ここでは、SQL Server はあまり制御できません。速度を上げる方法はすべて自分の手に委ねられています。その時間は CPU サイクルに費やされず、IO が完了するのを待つために費やされ、要求する負荷に合わせて調整された IO サブシステムが必要です。

IO 負荷を減らすには、インデックスを狭くすることを検討する必要があります。主に、クラスター化インデックスが機能する範囲で最も狭いものであることを確認してください。次に、非クラスター化インデックスに未使用のスポリアスの大きな列が含まれていないことを確認します (私はそれを見ました...)。ページの圧縮を有効にすると、大きな効果が得られる場合があります。そして最終的に、sys.dm_db_index_usage_statsのインデックス使用統計を調べて、斧に適したインデックスがあるかどうかを確認します。

IO 負荷を大幅に削減できない場合は、分割してみてください。ファイル グループをデータベースに追加し、大きなインデックスを別のファイル グループに移動し、ファイル グループを別の IO パス (個別のスピンドル) に配置します。

今後の定期的な削除操作では、パーティションの切り替えを使用し、すべてのインデックスをクラスター化されたインデックスのパーティション分割に合わせて配置し、時間になったら最後のパーティションを削除して超高速で削除することをお勧めします。

于 2010-01-15T20:32:22.653 に答える
3

テーブル内の各レコードに 5 つのインデックス レコードがあるとします。

これで、各削除は本質的に 5 つの操作になります。

それに加えて、クラスター化インデックスがあります。クラスター化インデックスの削除時間が非常に長いことに気付きましたか? (10x) 他のインデックスより長い? これは、すべてのレコードが削除されてデータが再編成されているためです。

再適用するよりも、少なくともそのインデックスを削除して一括削除することをお勧めします。削除と挿入のインデックス操作は、本質的にコストがかかります。単一の再構築は、おそらくはるかに高速です。

于 2010-01-15T20:16:58.773 に答える
2

@NickLarsenがコメントで行った提案に賛成します。未使用のインデックスがあるかどうかを調べて削除します。これにより、これらのインデックス削除のオーバーヘッドが削減される可能性があり、操作をよりタイムリーにするのに十分な改善になる可能性があります。

もう 1 つのより抜本的な戦略は、すべてのインデックスを削除し、削除を実行してから、小さくなったデータ セットのインデックスをすばやく再作成することです。これにより必ずしもサービスが中断されるわけではありませんが、その間にクエリが大幅に遅くなる可能性があります。私は Microsoft SQL Server の専門家ではありませんが、この戦略に関する私のアドバイスは、一粒の塩分で受け取ってください。

于 2010-01-15T20:04:31.200 に答える
1

これが本番環境であることを考えると、実装には多少の作業が必要ですが、SQL Server 2005 / 2008 を使用している場合は、テーブルを調査してパーティション分割に変換する必要があります。古いデータの削除は非常に迅速に実行できます。これは「ローリング ウィンドウ」タイプの効果用に設計されており、大規模な削除によってテーブルやプロセスが拘束されるのを防ぎます。

残念ながら、運用中のテーブルでは、この手法に移行するには、T-SQL コーディング、知識、およびアップグレード/移行に週末が必要です。既存の選択と挿入はシームレスに機能しますが、パーティションのメンテナンスと追加/削除は、プロセスを制御するためにt-sqlが必要な場所です。

于 2010-01-15T19:51:55.340 に答える
1

より多くの回避策ですが、行を削除するのではなくIsDeleted、テーブルにフラグを追加して更新できますか? このフラグを使用するには、1を変更する必要があります。SELECTsUPDATEs

次に、時間外にこれらのレコードの削除またはアーカイブをスケジュールできます。

于 2010-01-15T19:39:25.883 に答える