web-dev-qa-db-ja.com

SELECTがPKではなく非PKインデックスを使用しています

の中に [dbo].[Programs]テーブル、列[Id]はPrimaryKeyです(複合キーの一部ではありません)。そのテーブルには他にもかなり多くのインデックスがあります。

この単純なクエリを実行すると、SELECT [Id] FROM [dbo].[Programs]、ここに実行計画があります:

ExecutionPlan

私の質問は次のとおりです:PKインデックスを代わりに使用しないのはなぜですか?

テーブルには23行あるため、パフォーマンスは問題になりませんが、奇妙だと思います。なぜSqlServerが正しいのか、なぜSqlServerが優れていると誤解しているのかを理解したいのです。

5
Tipx

クエリオプティマイザーは、データを取得するための最も簡単な方法(それが可能な限り)を調べます。

ORDER BY [Id]を追加して、同じクエリの実行プランを確認するのは興味深いかもしれません。

Idは主キーであるだけでなく、そのインデックスはテーブルのクラスター化インデックスであると想定します。つまり、インデックスを調べてIdの値を取得するには、テーブル全体を読み取る必要があります(クラスター化インデックスは実際にはテーブル全体であり、インデックスキーで並べ替えられているため)。

また、IX_SupplyProgramIdには他にも限られた数の列が含まれていると想定します。すべてのインデックスにはクラスター化インデックスの値が含まれることに注意してください。これにより、インデックスが実際の行に接続されます。そして、Idのすべての値が含まれます

そのため、クラスター化インデックスを読み取る場合に読み取る必要のあるデータの量は、他のインデックスで読み取る量よりもおそらく多くなります。読み取りはクエリエンジンが行う最も負荷の高い操作の1つであるため、読み取りを減らすことは良いことです。

そのため、クラスター化インデックスの代わりに、より小さいインデックスを使用してId値を取得します。

8
RDFozz

通常、主キーがクラスター化されていることを除いて、主キーとは関係ありません。

SQL Serverはクラスター化インデックスを使用していません。定義により、クラスター化インデックスにはテーブル内のすべての列が含まれているためです。必要なのはIdだけなので、作業量が少ないという理由でクエリを満たすスキニーなインデックスを使用しています。テーブルに列が1つしかない場合でも、クラスター化されていないものを選択しますインデックス。

冷蔵庫からビールをもらうように頼んだら、次の選択肢があります。

  1. 冷蔵庫全体にホイール
  2. 事件をもたらす
  3. ビールを一杯持ってくる

あなたの場合、1はクラスター化インデックスを使用し、2はワイドインデックスを使用し、3はIdのみを含むインデックスを使用しています。

クラスター化されたインデックスは、常にフェラーリがタスク(たとえば、誰かを競争させることとヨットを牽引すること)のために常に使用したい自動車ではないように、操作にとって必ずしも常に最良の選択であるとは限りません。

10
Aaron Bertrand