38

実行速度が非常に遅いクエリのパフォーマンスを改善しようとしています。実際の実行計画を経て; Clustered Index Seekが 82% を占めていることがわかりました。Index Seekのパフォーマンスを向上させる方法はありますか?

索引:

/****** 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]
4

9 に答える 9

27

ここでは一般化していますが...

クラスター化されたインデックスのシークは、ほとんどの場合、最良のシナリオです。パフォーマンスを向上させるために私が考えることができる唯一の方法は次のとおりです。

  • 可能であれば、より少ない行/列を返すようにクエリを更新します。
  • インデックスを最適化または再構築します。
  • 複数のディスク/サーバー間でインデックスを分割します。

138 行しか返されず、それほど遅い場合は、他のプロセスによってブロックされている可能性があります。これを単独でテストしていますか、それとも他のユーザー/プロセスを同時にオンラインにしていますか? または、ディスク障害などのハードウェアの問題でさえあるかもしれません。

于 2009-12-28T19:22:36.857 に答える
17

クラスタ化インデックスシークは、非クラスタ化インデックスが使用されている場合に発生し、必ずしも悪いわけではありません。

次のクエリについて考えてみます。

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サーバーに新しいオプションが追加されました。非クラスター化インデックスを使用してシークすることを選択できます。これにより、State='TX'の行が生成されます。ただし、残りの列をSELECTに戻すには、各行に対してクラスター化インデックスシークを実行してそれらの列を検索する必要があります。

クラスタ化インデックスのシークを減らしたい場合は、追加の列を含めることでインデックスを「カバー」することができます。

 CREATE INDEX IX_Stu_State2 on Stu (State) INCLUDE (name, address, city )

このインデックスには、上記のクエリに回答するために必要なすべての列が含まれています。クエリは、State ='TX'である行のみを返すインデックスシークを実行し、追加の列を非クラスター化インデックスから引き出すことができるため、クラスター化インデックスシークはなくなります。

于 2013-01-30T06:59:56.793 に答える
9

138 行を返すクラスター化インデックス範囲シークは問題ではありません。

技術的には、クラスター化されたインデックスを狭くすることで、シークのパフォーマンスを向上させることができます。

  • 「行外の大きな値の型」を 1 に設定し、テーブルを最初から再作成することにより、すべての varlengtht を別のアロケーション ユニットに追い出します)。
  • ページ圧縮を有効にします(SQL 2008 EE のみ)。

どちらも、IO と物理読み取りをヒットする必要性を減らすため、範囲のシーク時間に非常に劇的な影響を与える可能性があります。もちろん、通常どおり、結果は、どの列を射影するかなど、他の多くの要因によって異なります (射影された列を BLOB アロケーション ユニットに追い出すと、実際には特定のクエリに悪影響を与える可能性があります)。補足として、通常、フラグメンテーションは、このような短距離スキャンにわずかな影響しか与えません。繰り返しますが、それは依存します。

しかし、私が言うように、これがあなたの本当の問題であるとはとても思えません。計画の選択された部分と独自の分析結果のみを投稿しました。真の根本原因は完全に別の場所にある可能性があります。

于 2009-12-28T19:59:59.767 に答える
3

いくつかの一般的なアドバイス: クエリの最適化を行う必要がある場合、実行計画がどうあるべきかを書き出すことから始めます。

実行計画がどうあるべきかを決定したら、実際のクエリをこの計画に適合させようとします。これを行う手法は DBMS ごとに異なり、必ずしも DBMS 間で移行できるわけではなく、異なるバージョンの DBMS 間で移行できる場合もあります。

覚えておくべきことは、DBMS は一度に 1 つの結合しか実行できないということです。2 つの初期テーブルから開始し、それらを結合し、その操作の結果を取得して次のテーブルに結合します。各ステップの目標は、中間結果セットの行数を最小限に抑えることです (より正確には、中間結果を生成するために読み取る必要があるブロックの数を最小限に抑えることができますが、これは通常、行数が最も少ないことを意味します)。

于 2009-12-28T20:32:10.027 に答える
3

考え...

  • IX_Stu がクラスター化されているのはなぜですか? 内部的に、SQL Server は、一意でないクラスター化インデックスに 4 バイトの "uniqueifier" を追加します。正当化は何ですか?これにより、PKも肥大化します

  • 実行している実際のクエリは何ですか?

  • 最後に、なぜ FILLFACTOR 80% なのか?

編集:

  • 「通常の」FILLFACTOR は 90% ですが、これはあくまでも経験則です。

  • 11 結合クエリ? それはおそらくあなたの問題です。あなたのJOIN、WHERE句などは何ですか? 全文プランとは?

于 2009-12-28T19:28:19.717 に答える
2

次のように、 WHERE条件をハードコードするとどうなりますか。

SELECT StuCertKey, StuKey FROM stu 
WHERE stuKey in (/* list 50 values of StuKey here */)

それでも非常に遅い場合は、何らかの内部問題が発生しています。より高速な場合、インデックスはボトルネックではなく、 WHEREフィルターを作成するために行っているJOINです。

SELECT *多くの大きな列がある場合、特に BLOB がある場合は、非常に遅くなる可能性があることに注意してください。

于 2009-12-28T19:56:58.473 に答える
1

このインデックスのメンテナンスを試みましたか? デフラグが好きですか?それがそんなにかかるのは本当に奇妙に思えます(120.381)。インデックス シークは最速のインデックス操作であり、それほど時間はかかりません。クエリを投稿できますか?

于 2009-12-28T19:20:28.000 に答える
0

インデックスを再構築し、統計を計算しますか?

速度を上げるために私が考えることができる唯一の他の方法は、テーブルを分割することです。これは、可能である場合と不可能である場合があります。

于 2009-12-28T19:22:26.473 に答える