この質問は、カバリングインデックスのINCLUDE
としてvarchar(2000)
を使用したSQL Serverインデックスのパフォーマンスに関するものです。
低速で不安定なデータベースアプリケーションのパフォーマンスを改善しようとしています。場合によっては、SUBSTRING()
、SPACE()
、DATALENGTH()
などの複数の文字列操作を含むクエリを使用して、大きなvarchar文字列を通じてデータにアクセスします。アクセスの簡単な例を次に示します。
_update fattable set col3 =
SUBSTRING(col3,1,10) + '*' +
SUBSTRING(col3,12,DATALENGTH(col3)-12)
from fattable where substring(col3,10,1) = 'A' and col2 = 2
_
スキーマは次のようになります。
_CREATE TABLE [dbo].[FatTable](
[id] [bigint] IDENTITY(1,1) NOT NULL,
[col1] [nchar](12) NOT NULL,
[col2] [int] NOT NULL,
[col3] [varchar](2000) NOT NULL, ...
_
次のインデックスが定義されており、大きなテキスト列にカバーフィールドがあります。
_CREATE NONCLUSTERED INDEX [IndexCol2Col3] ON [dbo].[FatTable] ( [col2] ASC )
INCLUDE( [col3] )
_
私が読んだことから、大きなデータフィールドをインデックスに入れるのは悪いことです。 http://msdn.Microsoft.com/en-us/library/ms190806.aspx を含むいくつかの記事を読んでおり、ページングとディスクサイズがインデックスのパフォーマンスに与える影響について説明しています。そうは言っても、クエリプランは間違いなくカバリングインデックスを使用します。これが実際にシステム負荷の点でどれだけのコストがかかっているかを判断するのに十分な情報がありません。全体として、システムのパフォーマンスが悪いことは知っています。これが問題の1つであることを心配しています。質問:
このvarchar(2000)
列をインデックスINCLUDE
に入れるのは良い考えですか?
INCLUDE
フィールドはリーフノードに格納されているので、インデックスのパフォーマンスに大きな影響を与えますか?
更新:素晴らしい返信をありがとう!これはいくつかの点で不公平な質問です-皆さんが言うように、実際の統計とプロファイリングなしには絶対的な正しい答えはありません。非常に多くのパフォーマンスの問題と同様に、答えは「依存する」と思います。
大きな言葉ですが、一般的には、いいえ、varchar(2000)フィールドをINCLUDEに入れません。
ええ、ページレベルでのデータの格納方法は、インデックスの使用方法によっては、インデックスのパフォーマンスに深刻な影響を与える可能性があります。
重要なのは、ページに詰め込むことができるデータの行が多いほど、アクセスする必要のあるページが少ないほど、システムが高速になることです。非常に大きな列を追加すると、ページに保存される情報が少なくなるため、範囲のシークまたはスキャンの場合、データを取得するためにより多くのページを読み取る必要があり、処理速度が大幅に低下します。
これがクエリまたはシステムの問題であるかどうかを確実に知るには、読み取り、特にクエリが使用するページ数を監視する必要があります。
現在のクラスター化インデックスキーを確認し、col2
代わりにクラスター化インデックスキー?このようにして、データを複製せずに、カバーする「インクルード」動作を得ることができます(クラスター化インデックスは常にすべてを「含む」ため)。もちろん、これは多くのif
とbut
の影響を受けますが、おそらく検討する価値があります。もちろん、現在のクラスター化インデックスが制約(主キー、一意)を適用している場合は、その制約を非クラスター化インデックスに移動する必要があります。
答えるのは難しいです。それはすべて、読み取りと書き込みの比率に依存します。ワークロードをテストしたか、含まれている列がある場合とない場合のテストシステムでビジネスサイクル全体をシミュレートしましたか?それを使わないルックアップは多くのコストがかかるかもしれませんが、データを読んでいるよりも頻繁にデータを更新している場合、それは大丈夫かもしれません。
私はこのパーティーに遅れていることを知っていますが、substring(col3,10,1)など、行を見つけるために使用される式を正確にインデックス付けします。 col3全体が使用される場合は、CHECKSUM(col3)にインデックスを付けます(もちろん衝突が発生する可能性があることを理解しています)。