大きなインデックスのINCLUDEフィールドはシステムパフォーマンスにどのように影響しますか?


15

この質問は、とSQL Serverのインデックスのパフォーマンスについてですvarchar(2000)としてINCLUDEの被覆指数インチ

低速で不安定なデータベースアプリケーションのパフォーマンスを改善しようとしています。いくつかのケースでは、データのようなmultple文字列操作を含むクエリで、大VARCHAR列を介してアクセスされるSUBSTRING()SPACE()DATALENGTH()。アクセスの簡単な例を次に示します。

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フィールドはリーフノードに格納されるため、インデックスのパフォーマンスに大きな影響がありますか?

更新:すばらしい返信をありがとう!これはいくつかの点で不公平な質問です-皆さんが言うように、実際の統計とプロファイリングなしに絶対的な正しい答えはありません。多くのパフォーマンスの問題と同様に、答えは「それは依存する」と思います。


実際の値はどれくらいですか?A VARCHAR(2000)一般的にちょうど10文字を格納一つのことです。1レコードあたり2,000バイトの固体は別のものです。
ジョンオブオールトレードズ

単なる観察:ここで「臭い」とは、大きな列に1)フリーテキスト(その場合、クエリはFULLTEXTインデックスを使用するように書き換えることでメリットが得られる)または2)「人間が読み取れる」コード化データ(たとえば、ワイドインテリジェントキー(VINなど))は、別々の列に分割したり、INDEXを使用して永続化された計算列にしたりすることでメリットが得られます。言い換えれば、インテリジェンスとデータ変更の流れはうまく設計されていません。
グレアム

1
はい#Graeme、ここには悪臭があります-「レガシー」と呼ばれると思います。このデータベースには多くの問題があります。
ラウルルビン

回答:


14

これまでは大きな言葉ですが、一般的にいや、INCLUDEにvarchar(2000)フィールドを入れません。

ええ、ページレベルでのデータの保存方法は、インデックスの使用方法によっては、インデックスのパフォーマンスに深刻な影響を与える可能性があります。

大事なことは、ページに詰め込むことができるデータの行が多くなればなるほど、アクセスする必要のあるページが少なくなり、システムがより速くなるということです。非常に大きな列を追加すると、ページに保存される情報が少なくなるため、範囲のシークまたはスキャンの場合、データを取得するためにより多くのページを読み取らなければならず、データの処理速度が大幅に低下します。

これがクエリの問題なのか、システムの問題なのかを確実に知るには、読み取り、特にクエリが使用するページ数を監視する必要があります。


ありがとう、Grant。別のコメントで述べたように、優れたパフォーマンス情報は不足しているため、抽象的な質問です。ページサイズのパフォーマンスコストを監視した経験はありません。私の予感は、それが問題であり、いくつかの統計を取得できるかどうかを確認することです。
ラウルルビン

1
クエリの統計IOをオンに設定すると、多くのことがわかります。論理読み取りはアクセスされたページの数を表します。また、perfmonカウンタからの秒数/読み取りを監視して、一般的なパフォーマンス情報を取得することもできます。
グラントフリッチー

6

現在のクラスター化インデックスキーを確認し、col2代わりにクラスター化インデックスキーを作成することはできますか?この方法で、データを複製することなく、「クラスター化されたインデックスは常にすべてを含む」ため、「含める」動作をカバーします。もちろん、これは多くの対象とifなりますがbut、おそらく検討する価値があります。もちろん、現在のクラスター化インデックスが制約(主キー、一意)を強制している場合、その制約は非クラスター化インデックスに移動する必要があります。


PKについてのあなたの提案は素晴らしいアイデアですが、この場合は適用できませんが、他のクエリには既存のPKが必要です。(これは私がツールボックスに保持するテクニックです!)
ラウルルビン

4

答えるのは難しいです。それはすべて、読み取りと書き込みの比率に依存します。含まれている列の有無にかかわらず、テストシステムでワークロードをテストしたり、ビジネスサイクル全体をシミュレートしたことがありますか?これを使用しない検索には多大な費用がかかる可能性がありますが、データを読むよりも頻繁にデータを更新している場合は問題ありません。


全体的な読み取りと更新のバランスがほぼ取れています。組織およびプライバシーの問題により、有用な統計と現実的なテストを取得することが難しくなります。私たちはほとんど盲目に飛んでいるので、抽象的な視点から物事を見る必要があります(この質問のため)。テストとは、生産に変更をプッシュし、結果を観察することを意味します-非常に危険です。
ラウルルビン

2
そして、ほとんどの読み取りが実際にこのVARCHAR(2000)列をプルしますか、それともほとんどのクエリを表さない非常に具体的なクエリのパフォーマンスをトラブルシューティングしていますか?Grantが、この列が多くのクエリで使用されていない場合、または実際にシークの問題が発生している場合は、必要なときにルックアップの価格を支払うことをお勧めしますが、不要な場合はストレージの料金を支払うことはできません。繰り返しますが、フェンスのどちら側にいるべきかを判断するのは非常に困難です。なぜなら、私たちには実際には詳細が何もないからです(そして、テストすることができないのでさらに難しい-あなたはそれを修正するよう努める必要があります)。
アーロンバートランド

3

私はこのパーティーに遅れていることは知っていますが、substring(col3,10,1)など、行の検索に使用される式に正確にインデックスを付けます。col3全体を使用する場合、CHECKSUM(col3)をインデックス付けします(もちろん衝突が発生する可能性があることを理解します)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.