クラスター化されたインデックスシークのパフォーマンスを改善する方法
-
21-09-2019 - |
質問
非常にゆっくりと実行されているクエリのパフォーマンスを改善しようとしています。を通過した後 実際の実行計画;私はそれを見つけました クラスター化されたインデックスシーク 82%を占めていました。私がパフォーマンスを改善する方法はありますか インデックスシーク?以下は問題の画像です インデックスシーク 実行プランとそれが使用しているインデックスとテーブルから。
Alt Text http://img340.imageshack.us/img340/1346/seek.png
索引:
/****** Object: Index [IX_Stu] Script Date: 12/28/2009 11:11:43 ******/
CREATE CLUSTERED INDEX [IX_Stu] ON [dbo].[stu]
(
[StuKey] ASC
)WITH (PAD_INDEX = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]
表(簡潔にするために省略されたいくつかの列):
CREATE TABLE [dbo].[stu](
[StuCertKey] [int] IDENTITY(1,1) NOT NULL,
[StuKey] [int] NULL
CONSTRAINT [PK_Stu] PRIMARY KEY NONCLUSTERED
(
[StuCertKey] ASC
)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY]
解決
私はここで一般化していますが...
クラスター化されたインデックスシークは、ほとんどの場合、ベストケースシナリオです。パフォーマンスを改善するために考えることができる唯一の方法は、次のとおりです。
- クエリを更新して、可能であれば、より少ない行/列を返します。
- インデックスを解体または再構築します。
- 複数のディスク/サーバーにわたってインデックスをパーティションします。
それが138行しか返さず、それがそんなに遅い場合...多分それは他のプロセスによってブロックされているのでしょうか?これを単独でテストしていますか、それとも他のユーザー/プロセスを同時にオンラインで使用していますか?または、ディスクの障害のようなハードウェアの問題でさえあります。
他のヒント
クラスター化されたインデックスの探求は、クラスター化されていないインデックスが使用されている場合に発生し、必ずしも悪いとは限りません。
次のクエリを検討してください。
SELECT s.StuKey, s.Name, s.Address, s.City, s.State FROM stu s WHERE State='TX'
Stukeyにクラスター化されたインデックスのみがある場合、SQL Serverには1つのオプションしかありません。State= "Tx 'で行を探し、それらの行を返す行全体をスキャンする必要があります。
状態にクラスター化されていないインデックスを追加する場合
CREATE INDEX IX_Stu_State on Stu (State)
これで、SQL Serverには新しいオプションがあります。非クラスター化されたインデックスを使用することを選択できます。これにより、state = 'tx'の行が生成されます。ただし、選択に残りの列を取得するには、各行のクラスター付きインデックスシークを実行して、それらの列を検索する必要があります。
Clustered Index Seeksを減らしたい場合は、追加の列を含めることでインデックスを「カバー」することができます。
CREATE INDEX IX_Stu_State2 on Stu (State) INCLUDE (name, address, city )
このインデックスには、上記のクエリに答えるために必要なすべての列が含まれるようになりました。クエリは、state = 'tx'の行のみを返すためのインデックスを実行し、追加の列をクラスター化されていないインデックスから引き出すことができるため、クラスター化されたインデックスが消えます。
138行を返すクラスター化されたインデックス範囲があなたの問題ではありません。
技術的には、クラスター化されたインデックスを狭くすることで、シークのパフォーマンスを改善できます。
- すべてのvarlenghtを設定して別の割り当てユニットに排除します '列のない大きなバリュータイプ'1に、テーブルをゼロから再現します)。
- 有効 ページ圧縮 (SQL 2008 EEのみ)。
どちらも、IOが減少し、物理的な読み取りを打つ必要性を減らすため、範囲シーク時間に非常に劇的な影響を与える可能性があります。もちろん、通常のように、結果は、どの列を投影するかなど、他の多くの要因で異なります(BLOB割り当てユニットに投影された列を排除すると、実際に特定のクエリに悪影響を与える可能性があります)。サイドノートとして、通常、断片化はこのような短距離スキャンにわずかな影響しかありません。繰り返しますが、それは依存します。
しかし、私が言うように、私はこれがあなたの本当の問題であることを非常に疑います。計画の選択された部分と独自の分析の結果のみを投稿しました。真の根本的な原因は、他の場所に完全に横たわる可能性があります。
考え...
IX_STUがクラスター化されるのはなぜですか?内部的には、SQL Serverは、非ユニークなクラスタリングインデックスに4バイト「一意」を追加します。正当化とは何ですか?これもあなたのPKも膨らませます
実行中の実際のクエリは何ですか?
最後に、なぜFillFactor 80%?
編集:
「通常の」塗りつぶしは90%ですが、これは経験則のみです
11の参加クエリ?それはおそらくあなたの問題です。あなたの参加は何ですか、条項などはどこですか?全文計画とは何ですか?
いくつかの一般的なアドバイス:クエリの最適化を行わなければならないとき、私は実行計画がどうあるべきかを書き始めることから始めます。
実行計画がどうあるべきかを決めたら、実際のクエリをこの計画に合わせてみようとします。これを行う手法は、各DBMSで異なり、DBMSの異なるバージョン間で、必ずしも一方から他方に、あるいは時には、時には異なるバージョン間で転送されるわけではありません。
心に留めておくべきことは、DBMSが一度に1つの結合のみを実行できることです。2つの初期テーブルで始まり、それらに加わり、その操作の結果を取得して次のテーブルに結合します。各ステップでの目標は、中間結果セットの行数を最小化することです(より正確には、中間結果を生成するために読み取る必要があるブロックの数を最小限に抑えることですが、これは一般に最も少ない行を意味します)。
このインデックスのメンテナンスを試しましたか?デフラグのように?それがそれほど費用がかかることは本当に奇妙に思えます(120.381)。インデックスシークは、最速のインデックス操作であり、それほど長くはかかりません。クエリを投稿できますか?
あなたがあなたのハードコードをした場合はどうなりますか どこ このような基準:
SELECT StuCertKey, StuKey FROM stu
WHERE stuKey in (/* list 50 values of StuKey here */)
それでも非常に遅い場合は、内部の問題があります。それがより速い場合、インデックスはあなたのボトルネックではありません、それは 参加 あなたが作成するためにしていること どこ フィルター。
ご了承ください SELECT *
多くの大きな柱がある場合、特に塊がある場合は非常に遅くなる可能性があります。
インデックスの統計を確認してください。
クラスター化インデックス統計を再計算すると、問題が解決します。
私の場合、私は40mの記録に30のレコードを探していました。実行計画によると、クラスターインデックスを通過しているが、約200ミリ秒かかった。そして、インデックスは解体されていませんでした。統計を再計算した後、10分以内に行われます!
インデックスを再構築し、統計を計算しますか?
私がそれをスピードアップするために考えることができる唯一の他の方法は、テーブルを分割することです。