0

約550万件のレコードがあるテーブルがあります。日付に基づいていくつかのレコードを削除する必要があります。私のクエリは次のようになります。

DELETE FROM Table WHERE [Date] between '2011-10-31 04:30:23' and '2011-11-01 04:30:42'

約9000行ですが、この操作は非常に長時間続きます。どうすればスピードアップできますか?日付はdatetime2のタイプであり、テーブルにはint主キーがクラスター化されています。更新および削除トリガーは無効になっています。

4

2 に答える 2

2

[Date] がすべての行で文字列にキャストされている可能性が非常に高く、その結果、テーブル全体が順次スキャンされます。

代わりに、パラメーターを日付にキャストしてみてください。

DELETE FROM Table WHERE [Date] between convert(datetime, '2011-10-31 04:30:23') and convert(datetime, '2011-11-01 04:30:42')

また、インデックスがあることを確認してください[Date]

于 2011-12-08T19:45:48.267 に答える
1

まず、日付にインデックスがあることを確認してください。

インデックスがある場合は、実行計画をチェックし、それが使用されていることを確認してください。インデックスの使用が削除を処理する最も効率的な方法であるとは限らないことに注意してください。大部分のレコードを削除する場合 (経験則では 10% を超えます)、インデックスの追加のオーバーヘッドが見えるためです。 up は、フル スキャンよりも大きくなる可能性があります。

大きなテーブルでは、統計が最新であることを確認することも重要です ( sp_updatestatsを実行します)。これは、データベースがテーブル内の行数を正しく理解していないと、実行計画で不適切な選択を行うためです。たとえば、統計が正しくない場合、データベースはインデックスが存在する場合でも、テーブル内のレコードが実際よりもはるかに少ないと判断して、インデックスを無視することを決定する場合があります。日付の奇数分布は、同様の効果をもたらす可能性があります。

おそらく日付のインデックスを削除してから、再度作成してみてください。インデックスはバイナリ ツリーであり、効率的に機能するにはバランスを取る必要があります。時間の経過とともにデータが蓄積されると、インデックスが偏ってしまい、クエリで適切なデータを見つけるのに時間がかかることがあります。この問題と統計の問題はどちらも、データベース メンテナンス ジョブによって自動的に処理されるはずですが、見過ごされがちです。

最後に、テーブルに他の多くのインデックスがあるかどうかはわかりません。存在する場合は、データベースがインデックスを更新するだけでなく、削除を進めるときにインデックスを再編成しなければならないという問題が発生している可能性があります。少し抜本的ですが、削除を実行する前にテーブルの他のすべてのインデックスを削除し、後でそれらを再度作成するという 1 つのオプションがあります。

于 2011-12-08T20:07:16.970 に答える