2

tbl_event非クラスター化インデックスで呼び出され、次のようIDX_Event_FolderIDX_Event_Time定義されたデータベーステーブルがあります。

CREATE NONCLUSTERED INDEX [IDX_Event_Folder] 
ON [dbo].[tbl_event]([nobjectid] ASC)

CREATE NONCLUSTERED INDEX [IDX_Event_Time] 
ON [dbo].[tbl_event]([tetime] ASC)

次の簡単なクエリを実行し、実行プランを真下に表示しました。

クエリ1:

SELECT * 
FROM tbl_event 
WHERE tbl_event.nobjectid = 1410000
ORDER BY tetime

クエリ1の実行プラン

クエリ2:

SELECT * 
FROM tbl_event 
WHERE tbl_event.nobjectid = 1410000

クエリ2の実行プラン

私の質問は、なぜnobjectidのインデックスが使用されないのですか?これらのselectステートメントのwhere句でnobjectidが指定されている場合、インデックスのシークまたはスキャンが行われると思います。この分析についての私の理解は間違っていますか?

4

3 に答える 3

3

nobjectidのインデックスが使用されないのはなぜですか?where句でnobjectidが指定されている場合、インデックスシークまたはスキャンがあると思います

よくある誤解!

1つのポイントは、を使用しているSELECT *ため、テーブルのすべてのデータが必要です。したがって、最終的に、SQL Serverは実際のデータページに戻り、すべての値をフェッチする必要があります。

インデックスシークが発生してヒットが見つかった場合、この場合、SQLServerはブックマークルックアップを実行する必要があります。これはかなりコストのかかる操作です。

また、これらの操作はかなりコストがかかるため、SQL Serverは可能であればそれらを回避しようとします。そのため、多くの場合、代わりにテーブルスキャンが使用されます。これは、最終的にncインデックスを検索してブックマークルックアップを実行するよりも高速であるためです。 。

確認すべきポイント:

  • カラムはどの程度選択的ですか?nobjectidこれは多かれ少なかれ一意のIDのように聞こえます-それは良いことです。あまり選択的ではない列にインデックスがある場合、クエリオプティマイザはそれを無視することがよくあります(すでに多くの行をチェックする必要があるため、最終的にテーブルスキャンが高速になります)

  • テーブルには何ありますか?小さなテーブル(数千行未満)の場合、最初からテーブルスキャンを実行する方がはるかに高速であることがよくあります。

また、「RIDヒープルックアップ」を使用した最初の実行プランから、テーブルにクラスター化インデックスがないと結論付けます。すぐに追加してください。クラスタ化されたキーがない(したがって、クラスタ化されたテーブルの代わりにヒープがある)と、多くの操作が遅くなり、非クラスタ化インデックスの有効性が低下します。

「NUSE」列にクラスター化インデックスを追加してみてください。

  • 狭い
  • 個性的
  • 安定
  • 増え続ける

INT IDENTITYは完璧な候補です-UNIQUEIDENTIFIERまたは非常に幅広い複合列のセットが最悪です。キンバリー・トリップのブログで、適切なクラスター化されたインデックスの選択に関するすべてをお読みください

于 2011-02-09T18:18:31.050 に答える
2

コメントで、現在テーブルに18325170行があり、そのうちの約30行だけがnobjectid=1410000であると言います。

インデックスが無効になっている場合でも、IDX_Event_FolderSQL Serverがその行数に対してこのプランを選択することは信じられません。線の太さは、18325170ではなく1行を処理していると考えていることを示しています。

プラン

だから私はあなたが自動更新統計を無効にしなければならないとかなり確信していますか?その場合、統計を手動で更新する必要があります(またはできればこのオプションを有効にしてください)

于 2011-02-09T20:46:18.437 に答える
1

いくつかの重複することが起こっています

  • あなたのSELECT *意味は「私にすべての列を与えてください」。オプティマイザーは、代わりにテーブルをスキャンする方が便利であると判断します。
  • 唯一の有用なインデックスは、注文のためのtetimeインデックスです。これを実行してから、テーブルにドリルダウンします。
  • クラスタ化されたインデックスがありません(RID /ヒープルックアップはそれを示しています)
  • nobjectidインデックスに一意性がないことは役に立ちません。つまり、完全なインデックススキャンを意味します。oなぜインデックスと組み合わせて使用​​するの SELECT *ですか?

これがある場合、インデックスは(スキャンとして)使用されます

SELECT nobjectid
FROM tbl_event 
WHERE tbl_event.nobjectid = 1410000

または、これは、新しいインデックスが使用される可能性が最も高いです

CREATE NONCLUSTERED INDEX [IDX_Co,bined] 
ON [dbo].[tbl_event]([nobjectid] ASC, tetime)

SELECT nobjectid, tetime
FROM tbl_event 
WHERE tbl_nobjectid = 1410000
ORDER BY tetime

これらの記事を読むことをお勧めします

クラスター化されたインデックスの欠如は、これらの記事でもカバーする必要があります

于 2011-02-09T18:18:58.807 に答える