の中に [dbo].[Programs]
テーブル、列[Id]
はPrimaryKeyです(複合キーの一部ではありません)。そのテーブルには他にもかなり多くのインデックスがあります。
この単純なクエリを実行すると、SELECT [Id] FROM [dbo].[Programs]
、ここに実行計画があります:
私の質問は次のとおりです:PKインデックスを代わりに使用しないのはなぜですか?
テーブルには23行あるため、パフォーマンスは問題になりませんが、奇妙だと思います。なぜSqlServerが正しいのか、なぜSqlServerが優れていると誤解しているのかを理解したいのです。
クエリオプティマイザーは、データを取得するための最も簡単な方法(それが可能な限り)を調べます。
ORDER BY [Id]
を追加して、同じクエリの実行プランを確認するのは興味深いかもしれません。
Id
は主キーであるだけでなく、そのインデックスはテーブルのクラスター化インデックスであると想定します。つまり、インデックスを調べてId
の値を取得するには、テーブル全体を読み取る必要があります(クラスター化インデックスは実際にはテーブル全体であり、インデックスキーで並べ替えられているため)。
また、IX_SupplyProgramId
には他にも限られた数の列が含まれていると想定します。すべてのインデックスにはクラスター化インデックスの値が含まれることに注意してください。これにより、インデックスが実際の行に接続されます。そして、Id
のすべての値が含まれます
そのため、クラスター化インデックスを読み取る場合に読み取る必要のあるデータの量は、他のインデックスで読み取る量よりもおそらく多くなります。読み取りはクエリエンジンが行う最も負荷の高い操作の1つであるため、読み取りを減らすことは良いことです。
そのため、クラスター化インデックスの代わりに、より小さいインデックスを使用してId
値を取得します。
通常、主キーがクラスター化されていることを除いて、主キーとは関係ありません。
SQL Serverはクラスター化インデックスを使用していません。定義により、クラスター化インデックスにはテーブル内のすべての列が含まれているためです。必要なのはId
だけなので、作業量が少ないという理由でクエリを満たすスキニーなインデックスを使用しています。テーブルに列が1つしかない場合でも、クラスター化されていないものを選択しますインデックス。
冷蔵庫からビールをもらうように頼んだら、次の選択肢があります。
あなたの場合、1はクラスター化インデックスを使用し、2はワイドインデックスを使用し、3はId
のみを含むインデックスを使用しています。
クラスター化されたインデックスは、常にフェラーリがタスク(たとえば、誰かを競争させることとヨットを牽引すること)のために常に使用したい自動車ではないように、操作にとって必ずしも常に最良の選択であるとは限りません。