昨日と今日、ローカル インスタンスに復元したデータベースで特定のデータベース クエリの実行に時間がかかる (3 分以上) のをトラブルシューティングするために数時間を費やしましたが、本番環境ではわずか 1 秒しかかかりませんでした。サーバ。(同じクエリが以前にローカルインスタンスで正常に実行されていたため、本番サーバーのスペックが高いという問題だけではありません)。
できる限り最善の方法で問題を説明しようと思います。つまり、投稿が少し長くなる可能性があります。クエリは非常に簡単です。
SELECT [t0].[BillId], [t0].[CustomerId], [t0].[BillDate], [t0].[DueDate],
[t0].[Period], [t0].[Total], [t0].[Balance], [t0].[DateCreated], [t0].[DateModified] --, other fields
FROM [dbo].[Bills] AS [t0]
WHERE ([t0].[Period] = 201307) AND (([t0].[DateModified] >= '2013-07-04 17:00:00.000')
OR (([t0].[DateModified] < '2013-07-04 17:00:00.000') AND (EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[BillDetails] AS [t1]
WHERE [t1].[BillID] = [t0].[BillID] AND [t1].[DateModified] >= '2013-07-04 17:00:00.000'
))))
上記のクエリは、特定の期間に関連付けられ、特定の時点以降に変更された請求書を返します。DateModifiedフィールドの値が指定された日付よりも後の場合、または関連する子行 ( ) のDateModifiedフィールドの値が指定された日付よりも後の場合、請求書は変更されたと見なされBillDetails
ます。上記のクエリによって返された結果に関して、「デルタ」という言葉を使用します。
奇妙なことですが、私のローカルインスタンスでは、特にデルタがない場合、つまり最後に指定された日付以降にBills
変更がなかった場合、このクエリの実行は一種のブロックのように見えます。BillDetails
返されるデルタがある場合、クエリには数分の 1 秒かかります。ライブ/本番データベースでは、クエリは両方のシナリオで非常に高速に応答します。
以前にこの問題に遭遇したことがありますが、どのように修正したかを文書化していませんでした。その間、本番データベースで「ブロッキング」が発生していましたが、ローカル インスタンスは問題ありませんでした。インデックスと関係があるのではないかと疑っていました。
ローカルインスタンスで再発したとき、インデックスが主な容疑者でした。平均断片化が 5 ~ 30% のインデックスを再編成し、平均断片化が 30% を超えるインデックスを再構築するためのユーティリティ スクリプトを実行しました。それは問題を解決するようには見えませんでした。Bills
それ以来、私は多くのことを試しましたが、それを修正したのは、テーブルの非クラスター化インデックスを削除して再作成することです。
次のように定義されたテーブルに 3 つの非クラスター化インデックスがありBills
ます (多かれ少なかれ):
NCI_IDX1 ([CustomerId] ASC)
NCI_IDX2 ([CustomerId] ASC, [Period] ASC, [BillId] ASC)
NCI_IDX3_Inc_Various ([Period] ASC, [DateModified] ASC, [BillId] ASC, [CustomerId] ASC) INCLUDE ([BillDate], [Total], [Balance] /* more fields */)
問題を解決しようとしているときの経験から、いくつかの疑問が頭をよぎります。
Q : インデックスの再構築は何をしますか? インデックスを手動で削除して再作成するのと同じことをしますか?
Q : インデックスを削除すると、削除されたインデックスに関連付けられた統計が表示されます。インデックスを再構築すると、関連する統計が「更新」または「リセット」されますか?
Q : クエリ オプティマイザーが実行プランを選択する際に統計に依存していることを考えると、統計がクエリ実行のブロックと認識された原因になっている可能性はありますか?
Q : MSDN によると、 を使用してインデックスの統計を削除することはできませんDROP STATISTICS
。統計をリセットするには、インデックスを削除して再作成する必要があるということですか?
注: 上記のクエリの元はデータ層で LINQtoSQL を使用する C# アプリケーションであるため、LINQ と C# がタグ付けされています。