SQL Server上のほぼすべてのデータベースの断片化が40%を超えていることを確認した後、フィルファクター80を使用してすべてのテーブルでインデックスの再構築を行うことにしました。
すべてのインデックスを再構築した後、いくつかのクエリは、少なくとも2つのクエリ/テーブルに対して永遠にかかるようです。
遅いクエリの1つを次に示します。
_SELECT a.FileID,
a.EventID,
MAX(b.cyNumber) AS cyNumber,
MAX(b.skNumber) AS skNumber,
MAX(b.cyFormat) AS cyFormat,
MAX(b.Cost) AS Cost,
MAX(b.PackageRef) AS PackageRef,
MAX(CASE WHEN b.BMUpdatedON = '1900-01-01 00:00:00.000' THEN NULL ELSE b.BMUpdatedON END) AS BMUpdatedON,
MAX(b.RunID) AS RunID
FROM DB.dbo.[File] a
INNER JOIN DB.dbo.bicy b ON a.InnerFileID = b.InnerFileID
WHERE a.FileID NOT IN (SELECT FileID FROM DB.dbo.Event_bicy)
GROUP BY a.FileID,
a.EventID
OPTION (MAXDOP 1);
_
すべてのクエリで常にOPTION (MAXDOP 1)
を使用しました。使用しなかった場合、クエリの実行が非常に遅くなるためです。さて、インデックスの再構築後、逆のことが起こっているようです。 _MAXDOP 1
_を削除した場合、またはwhere
句を削除した場合、クエリが高速に実行されます。
解決策:_DB.dbo.bicy.[InnerFileID]
_で非クラスター化インデックスを作成すると、クエリが高速に実行されます。
質問:インデックスの再構築が正常に実行される前に、クエリを高速に実行するために非クラスター化インデックスを作成する必要があるのはなぜですか?
それ自体の断片化は、必ずしもそれが作り出された邪悪な悪魔であるとは限りません。データベースファイルがSAN、またはいくつかのタイプのRAIDアレイ、またはSSDに格納されている場合、ページが断片化されているかどうかに関係なく、ページ全体がディスク全体に分散されるため、インデックスの最適化による違いはほとんどありません。その説明については、この回答を参照してください。 SAN環境でSQLインデックスを最適化することにはメリットがありますか?
インデックスを再構築するときは、無差別に_FILL_FACTOR = 80
_を設定しないでください。この設定はテーブルごとに評価する必要があります。再構築の前にテーブルが_FILL_FACTOR = 100
_にあったと想定すると、各テーブルに必要なストレージが実質的に20%増加しています。これは、物事が現在遅くなっている理由の良い部分かもしれません。
すべてのクエリでOPTION (MAXDOP 1)
を使用することもお勧めできません。クエリエンジンが並列クエリを実行するかどうかを決定できるようにする必要があります。 _EXEC sp_configure 'max degree of parallelism', X
_を使用して、サーバーレベルで適切なMAXDOP
オプションを設定します。ここで、Xは並列クエリに使用するコアの最大数です。 MAXDOPの説明については、この質問を参照してください。 SQL ServerでMAXDOPを計算するための、繰り返し可能な優れた方法は何ですか?
1つまたは複数のフィールドに非クラスター化インデックスを追加すると、データベースエンジンがインデックスを使用する場合、クエリの実行が確実に高速になります。
影響を受けるテーブルのstatistics
が最新であることを確認したい場合があります。その方法のBooks Onlineの説明については、 http://technet.Microsoft.com/en-us/library/ms187348.aspx を参照してください。 SQLSkillsには、統計に関する優れた記事もあります。ここでは http://www.sqlskills.com/blogs/erin/understanding-when-statistics-will-automatically-update/