web-dev-qa-db-ja.com

実行計画に欠落したインデックスが表示されない

最近SQL Server Management Studio 2014(Developer Edition)をインストールしましたが、不足しているインデックス機能が表示されなくなっています。

私がやったこと:

  • Database Engine Tuning Advisorを介してワークロードを実行したので、テーブルにインデックスがないことがわかります。
  • この機能を有効にすることについてオンラインで何も見つかりませんでした
  • 関連していると思われるすべてのオプションをふるいにかけました。

任意の提案をいただければ幸いです。私は以前2014年より前にSQL Server 2012 Developer Editionを実行していました。

[〜#〜]更新[〜#〜]

場合によっては、不足しているインデックスを表示することができます。次の2つのクエリを見てください。

このクエリでは、実行プランに欠落しているインデックスは表示されていません。 WHERE句フィールドはvarchar(512)であり、この列にはインデックスがありません。

_SELECT SomeVarchar FROM SomeTable WHERE Name='Adam'
_

このクエリでは、実行プランに欠落しているインデックスが表示されています。 AgeINTです

_SELECT SomeVarchar20 FROM SomeTable WHERE Age=30
_

インデックスがありません:

_CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[SomeTable] ([Age])
INCLUDE ([SomeVarchar20])
_

また、VARCHAR(500)フィールドを使用してクエリを試行したところ、欠落したインデックスが返されました。今、本当に頭を掻いています。

6
Adam Scharp

まあ、チューニングアドバイザーが不足しているインデックスを表示している間、これはcurrent実行中のクエリがこのインデックスの恩恵を受けるという意味ではありません。現在の計画がインデックスの恩恵を受ける場合は、欠落しているインデックスが表示されるだけです。

これらのDMVの1つを確認することもできます。現在のdbの欠落したインデックスが表示されます。

_SELECT *
FROM sys.dm_db_missing_index_details
_

追加情報が必要な場合は、私からのこのクエリを使用することもできます。

_SELECT  id.index_handle, DB_NAME(id.database_id), id.object_id, id.statement AS object_name, 
        gs.avg_user_impact, gs.avg_total_user_cost,
        id.equality_columns, id.inequality_columns, id.included_columns,
        gs.unique_compiles, gs.user_seeks, gs.last_user_seek, gs.last_system_seek, 
        gs.user_scans, gs.last_user_scan, gs.system_scans
FROM sys.dm_db_missing_index_details as id
INNER JOIN sys.dm_db_missing_index_groups as g
        ON id.index_handle = g.index_handle
INNER JOIN sys.dm_db_missing_index_group_stats as gs
        ON g.index_group_handle = gs.group_handle
ORDER BY gs.avg_user_impact DESC
_

最後の更新に基づいて編集

さて、なぜあなたが提案を得ないのかを決定することは非常に簡単です。

まず、このクエリの推奨インデックスを取得する理由:

_SELECT SomeVarchar20 FROM SomeTable WHERE Age=30
_

以下に示すようにインデックスを作成すると、インデックスから完全にインデックスが提供されます。

_CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[SomeTable] ([Age])
INCLUDE ([SomeVarchar20])
_

SQL Serverは、インデックスで定義されているAgeを使用してデータページを検索できます。さらに、列_SomeVarchar20_のみを選択するため、インデックスのリーフレベルページ(INCLUDEで定義)に追加することが提案されています。これは、SQL ServerがBツリーアーキテクチャのAgeに基づいて適切なページを見つけるのに役立ちます。彼は、他のすべてのプロパティが存在するHEAPまたはクラスター化インデックスへのポインターを保持する最後の行を見つけた後、リーフレベルのページに含まれる列にもアクセスします。インデックス自体に表示するすべてのものを見つけたという事実により、彼はあなたのHEAPやクラスター化インデックスにそれ以上進むことはありません。これにより、読み取り(!)のパフォーマンスが大幅に向上します。

事実、この列にインデックスを追加するように提案されない理由は、私には非常に明確です。

_SELECT SomeVarchar FROM SomeTable WHERE Name='Adam'
_

Namevarchar(512)であると言います。これは、1つの値canが512バイトであることを意味します。実際、SQL Serverページは約8060バイトを保持できます。つまり、ページごとに最大16個の名前(512バイトを完全に使用しない場合はさらに多くの名前)を保存できます。 SQL Serverは多くのページで反復(シーク)する必要がある場合もあるため、これによってパフォーマンスが大幅に向上することはありません。実際、彼はそれらすべてのページを各_insert/update/delete_でさらに維持する必要があります。

SomeVarcharvarchar(512)の場合もある)だけを使用すると、リーフレベルのページが大幅に増加し、インデックスがさらに非効率になります。これが、SQL ServerがSELECTの不足しているインデックスヒントを提供しない可能性がある理由です。

うまくいけば、これはあなたの心の中の他のすべてのものを片付けるでしょう。それ以外の場合はお知らせください。

9
Ionic