Skip to content

MS_SQLServerIndex

nishi_74322014 edited this page Aug 13, 2026 · 1 revision

SQL Server のインデックス

概要

インデックスがないテーブルには基本的にデータの並び順に保証がないため、
これを検索する場合は、性能的に遅い「テーブル スキャン」を実行する。
このため、検索処理の効率化のために、検索条件に対応した「インデックス」を作成する。

SQL Server のインデックスには、

  • 「クラスタ化インデックス」
  • 「非クラスタ化インデックス」
  • 「カバリング インデックス」
  • 「付加列インデックス」
  • 「パーティション インデックス」(SQL Server パーティション分割
  • 「インデックス付きビュー」

の 6 種類のインデックスがある。

補足(最新化:これ以外のインデックス): 上記は行ストア(B ツリー)系の分類。
現在は用途別に以下も選択肢になる。

種類 導入 用途
列ストア インデックス 2012(更新可能は 2014〜) 集計・分析系(OLAP)。列単位で圧縮し、バッチ モード実行で桁違いに速い
フィルタ選択されたインデックス 2008 WHERE 条件付きの非クラスタ化インデックス。NULL 除外などでサイズを大幅削減
メモリ最適化インデックス 2014 In-Memory OLTP(ハッシュ / 範囲)
全文検索インデックス - 文章の全文検索
空間 / XML / JSON - それぞれの型に対する検索

特にフィルタ選択されたインデックスは、

CREATE NONCLUSTERED INDEX IX_Order_Active
    ON dbo.Orders (CustomerId)
    INCLUDE (OrderDate, Amount)
    WHERE Status = 'Active';

のように「実際に検索対象になる行だけ」を対象にでき、
本ページで扱う選択度の問題を回避する有力な手段である。

インデックス種類

「クラスタ化インデックス」

「クラスタ化インデックス」は Oracle の「索引構成表」と同じであり、
「電話帳の 50 音順索引」のように、データが順番に並べられたインデックスのことを言う。

  • SQL Server では、1 テーブルに対し「クラスタ化インデックス」を 1 つだけ作成可能。

  • SQL Server ではテーブルに「主キー」を設定すると、
    自動的に「クラスタ化インデックス」が作成される。

  • 「主キー」を「クラスタ化インデックス」にしたくないのであれば、
    主キー作成時に NONCLUSTERED キーワードを指定する。

「非クラスタ化インデックス」

「非クラスタ化インデックス」は Oracle の「索引」と同じであり、
「書籍の索引」のように、データとは別の領域に作られたインデックスのことを言う。

  • SQL Server では、1 テーブルに対し「非クラスタ化インデックス」を 249 個まで作成可能。

補足(最新化): 249 個は SQL Server 2005 までの上限で、
SQL Server 2008 以降は 999 個まで作成できる。
ただし、これは上限であって推奨ではない。
インデックスは更新時のオーバーヘッドとストレージを消費するため、
実務では 1 テーブルあたり 5〜10 個程度に収めるのが目安。
未使用インデックスは sys.dm_db_index_usage_stats で検出できる。

複合インデックス

  • キーとして構成されているカラムの全てが検索条件に指定されていなくても、
    キーの先頭から途中までのカラムが指定されていれば、インデックスが使われる。

補足(列順が決定的に重要): 上記は「先頭から連続して指定されていれば」
という意味であり、途中の列だけを指定してもシークには使えない。

インデックス (A, B, C) に対して、

検索条件 シーク可否
A = ?
A = ? AND B = ?
A = ? AND B = ? AND C = ?
B = ? ×(スキャンになる)
A = ? AND C = ? △(A でシークし C は残余述語)

このため、列順は
等値条件で使う列 → 範囲条件で使う列 → ORDER BY の列
の順に置くのが原則。
参考リンクの「複合インデックスの正しい列の順序」も同じ趣旨。

「カバリング インデックス」

  • 「カバリング インデックス」とは、「複合インデックス」を指す。
  • 「カバリング インデックス」は、インデックスに取得データを含めることで、
    ヒープ(のページ)へのジャンプを防止することができ、性能の向上が期待できる。

補足(用語の整理): 厳密には、
「カバリング インデックス」は構造の名前ではなく、
あるクエリに対する状態を指す言葉
である。
クエリが必要とする列がすべてそのインデックスに含まれていれば、
そのインデックスは「そのクエリをカバーしている」と言う。
実現手段が複合インデックス(キー列に並べる)と
付加列インデックス(INCLUDE)の 2 つ、という関係になる。
実行プラン上は Key Lookup / RID Lookup が消えることで確認できる
実行プランのグラフィカル表示)。

「付加列インデックス」

  • 「カバリング インデックス」には、

    • カバリング列がルート・中間・リーフ ページに含まれるため、
      • インデックス サイズが大きくなり、
      • スキャンや、シーク時の I/O 数が多くなり、
      • インデックス更新時のオーバーヘッドも高くなる。

    といった性能上の問題が存在する。

  • これを回避するために、
    SQL Server 2005 からサポートされた「付加列インデックス」が使用できる。

  • 「付加列インデックス」は、

    • 「カバリング インデックス」の欠点を補った機能であるため、
      基本的に「付加列インデックス」を利用することが推奨される。
    • 具体的には、リーフノードにのみカラムを追加する(列を付加する)ことで、
      ヒープ(のページ)へのジャンプを防止しつつ、インデックスのサイズも押さえる。

補足(INCLUDE のもう一つの利点): INCLUDE の列は
キーではないため、

  • キーのサイズ制限(900 バイト / 1700 バイト)にカウントされない
  • nvarchar(max) などキーにできない型も含められる

という利点もある。
「検索条件・結合条件・ORDER BY に使う列はキーへ、
SELECT で返すだけの列は INCLUDE へ」が設計の指針になる。

「パーティション インデックス」

SQL Server パーティション分割

「インデックス付きビュー」

  • ビューに一意「クラスタ化インデックス」を付与することで、
    「クラスタ化インデックス」を持つテーブルのように、
    ビューに結果セットを格納するものである(つまり実体が存在する)。

  • このため、特に結合・集計処理を伴う参照クエリで性能向上が期待できる。

  • 「インデックス付きビュー」には、「非クラスタ化インデックス」を追加できる。

インデックスの構造

インデックス ページ

インデックスの構造について説明する。

  • インデックスは「インデックス ページ」から構成されており、「インデックス ページ」は、

    • 同位層のページを繋ぐ「ポインタ」と、
    • 下位層のページへの「ポインタ」
    • および「キー値」

    によって構成される。

  • 「インデックス ページ」の

    • 最上位層は「ルート レベル ページ」
    • 最下位層は「リーフ レベル ページ」
    • 「ルート レベル ページ」と「リーフ レベル ページ」の
      中間のレベルは「中間レベル ページ」と呼ぶ。

インデックス ページ

「クラスタ化インデックス」

次に、「クラスタ化インデックス」の構造について説明する。

  • 「クラスタ化インデックス」は、テーブルで「クラスタ化キー
    (クラスタ化インデックスを作成する際に使用したキー)」を設定すると、
    そのキー値の昇順にデータが並び替えられて、
    「リーフ レベル ページ」が実際の「データ ページ」として構成される。

クラスタ化インデックス

ディスクI/Oのチューニング

「クラスタ化インデックス」でディスク I/O のチューニングが可能である。

  • 「非クラスタ化インデックス」で必要となる RID LookUp という処理が不要で、
    その分性能が良い。

  • テーブルに対して「範囲検索」、「順次アクセス」処理をする際に、
    目的のデータが同じ「データ ページ」にある確率が多くなり
    ディスク ヘッドの移動が少なくなる。

  • 「選択度の低い情報」(後述)であっても、
    「範囲検索」、「順次アクセス」で、効果を出し得るインデックスであると言える。

  • SQL Server では検索で多用される(と想定される)主キーには、
    デフォルトで「クラスタ化インデックス」が付与される。

    • しかし、この方法が必ずしも適切であるということにはならない。
      例えば、主キー以外のキーを使用した範囲スキャン検索の性能の向上が
      優先されるようなテーブルでは、主キーに「非クラスタ化インデックス」を付与し、
      「範囲スキャン検索」処理用のキーに「クラスタ化インデックス」を使用した方が、
      全体最適化に繋がることがある。

    • インサイド Microsoft SQL Server 2005 クエリチューニング&最適化編
      第4章 : クエリパフォーマンスのトラブルシューティング

      テーブルを主キー制約で宣言すると、規定でクラスタ化インデックスが
      主キー列に作成されますが、この方法が常に最適であるとは限りません。
      その名が示すとおり、主キーは一意であり、条件を満たす単一行を検索する場合は、
      非クラスタ化インデックスが非常に効率的です。
      『主キーの一意性は、非クラスタ化インデックスでも適用できるため、
      クラスタ化インデックスは、主キー制約を宣言するときに
      NONCLUSTERED のキーワードを追加して、
      クラスタ化インデックスが有効なものに対して確保しておきます。』

適合しないケース

また、以下のキーには適していないと言われている。

  • 頻繁に変更される列
    物理的な並び替えが必要になるため。

  • 広範なキー(複数の列・複数のサイズの大きな列を組み合わせたキー)

    • 「クラスタ化インデックス」を持つテーブルに追加した
      「非クラスタ化インデックス」のリーフ ページには、
      行識別子ではなく、「クラスタ化インデックス」のキー参照が格納される(後述)。
    • このため、「クラスタ化インデックス」のキーのサイズが大きくなると、
      「非クラスタ化インデックス」のサイズが大きくなるため。

補足(クラスタ化キーの選定基準): 上記に「ランダムな値でないこと」を
加えた 4 条件が定番の指針である。

条件 理由
狭い(narrow) 全非クラスタ化インデックスに複製されるため
一意(unique) 一意でないと内部で 4 バイトの uniquifier が付加される
静的(static) 変更されると行の物理移動が発生する
単調増加(ever-increasing) 末尾に追記されるためページ分割が起きない

4 つ目の観点から、ランダムな uniqueidentifier(GUID)を
クラスタ化キーにするのは避ける
べきとされる
(挿入位置が散らばり、ページ分割と断片化が多発する)。
どうしても GUID が必要なら NEWSEQUENTIALID() を使うか、
GUID は非クラスタ化の一意インデックスにして
クラスタ化キーは連番の代理キーにする。

逆に、単調増加キーへの高頻度な挿入は
**末尾ページへの競合(ラッチ競合、ホット スポット)**を生むことがある。
極端な高スループット環境では、この対策が別途必要になる。

その他

「クラスタ化インデックス」作成時には、
実際のデータ(ヒープ)を並べ替えた結果を格納しておくための作業領域として、
テーブル サイズの約 1.5 倍の空き領域が必要になるため注意が必要である。

参考

「非クラスタ化インデックス」

次に、「非クラスタ化インデックス」の構造について説明する。

  • 「非クラスタ化インデックス」は、一般的かつ汎用的なインデックスであり、
    「リーフ レベル ページ」には、行識別子が格納される。

  • 「非クラスタ化インデックス」では、「リーフ レベル ページ」から
    ヒープ(のページ)上の行情報を引くための、RID LookUp と言う処理が必要となる。

    • このため、「リーフ レベル ページ」 → ヒープ(のページ)へのジャンプ
      (これを RID LookUp と言い、場合によってはディスク ヘッドの移動を要する)
      が必要になるため、キーを使用した範囲スキャン検索で、
      データを収集するクエリの性能は、件数が多くなるほど向上しない。
    • また、「選択度の低い情報」(後述)も同様に、
      範囲スキャン検索性能が向上しないため効果が出ない。
  • また、「非クラスタ化インデックス」は、

    • 「クラスタ化インデックス」が存在しない場合
    • 「クラスタ化インデックス」が存在する場合

    で構造が異なる。

  • 非クラスター化インデックスのデザイン ガイドライン
    https://learn.microsoft.com/ja-jp/sql/relational-databases/sql-server-index-design-guide

「クラスタ化インデックス」が存在しない「非クラスタ化インデックス」

  • 「クラスタ化インデックス」が存在しない「非クラスタ化インデックス」の
    「リーフ レベル ページ」は「インデックス ページ」である。

  • 「データ ページ」は「クラスタ化インデックス」を作成した場合の
    「データ ページ」とは構造が異なり、「リンク リスト」はもたない。

    • このような「非クラスタ化インデックス」の「データ ページ」の集まりを
      「ヒープ」と呼ぶ。
    • 「ヒープ」では、データの行の順番は特定の順序では格納されず、
      「データ ページ」にも特定の順序はない。
  • 「クラスタ化インデックス」が存在しない「非クラスタ化インデックス」での
    「リーフ レベル(インデックス ページ)」ではポインタとして
    行識別子(ファイル ID、ページ ID、行 ID)を格納しており、
    その行識別子を使って「ヒープ」へジャンプし、検索対象データを探し出す。

「クラスタ化インデックス」が存在しない「非クラスタ化インデックス」

「クラスタ化インデックス」が存在する「非クラスタ化インデックス」

  • 「クラスタ化インデックス」が存在する「非クラスタ化インデックス」の
    「リーフ レベル ページ」は同様に「インデックス ページ」であるが、
    「ポインタ」として「行識別子」ではなく「クラスタ化キー」の値を格納している。

  • このため、「クラスタ化インデックス」が存在する「非クラスタ化インデックス」での検索は、

    • 最初に「非クラスタ化インデックス」を使用して検索し、
    • 「リーフ レベル ページ」で取得した「クラスタ化キー」の値を使用して
      「クラスタ化インデックス」を検索する。
    • 「非クラスタ化インデックス」のキーを使用して「クラスタ化インデックス」の
      キーのみ取得する場合は、非常に高速。

「クラスタ化インデックス」が存在する「非クラスタ化インデックス」

補足(用語): この 2 段階の検索は、実行プラン上では
ヒープの場合が RID Lookup
クラスタ化インデックスの場合が Key Lookup として現れる。
どちらも「1 行ごとにランダム I/O が発生する」ため、
件数が増えるとオプティマイザは
インデックスを諦めてテーブル全体をスキャンするプランに切り替える
tipping point と呼ばれる)。
「インデックスがあるのにスキャンされる」場合の主要な原因の 1 つで、
INCLUDE でカバーすれば解消することが多い。

「カバリング インデックス」

  • 「カバリング インデックス」は、以下により性能の向上が期待できる。

    • 最初に指定された列をキーにして、木構造を構築し、
    • 以降に指定された列(カバリング列)をルート・中間・リーフ ページに含める。
    • これにより、カバリング列に対しては RID LookUp をせずに処理が可能となる。
  • 例えば、下記 DDL で、「カバリング インデックス」が作成できる。

CREATE INDEX index_name
  ON table_name(column1, column2, column3)
  • この場合、
    • column1 をキーにして、木構造が構築され、
    • カバリング列として column2、column3
      ルート・中間・リーフ ページに含められる。

移行メモ(誤字): 元ページの「カバリンク列」は「カバリン列」の誤記。

「付加列インデックス」

  • 例えば、下記 DDL で、「付加列インデックス」が作成できる。
CREATE INDEX index_name
  ON table_name (column1)
   INCLUDE(column2, column3)

「パーティション インデックス」

SQL Server パーティション分割

「インデックス付きビュー」

  • GROUP BY 句を使用した集計処理で指定されるキーの
    選択度が高い(若しくは一意の)場合は、性能向上は期待できない。

  • また、「インデックス付きビュー」の基テーブルの更新がされると、

    • ビューに格納されている結果セットの更新が必要となるため、
      更新処理が頻繁なビューに対して「インデックス付きビュー」を作成すると
      余計にコストがかかる場合があるので注意する。
    • なお、条件を満たしていれば「インデックス付きビュー」の更新も可能であり、
      「インデックス付きビュー」の更新が行われた場合、基テーブルも更新される。
  • 考慮点

補足(自動利用はエディション依存): 「直接指定していないクエリからも
オプティマイザに使用される」(自動照合)のは、
Enterprise Edition(および Developer / Evaluation)に限られる
Standard Edition では、WITH (NOEXPAND) ヒントを付けて
明示的に参照する必要がある。

インデックスと選択度

  • 一般的にインデックスは、

    • 選択度が高い項目を検索条件に使用する場合に有用である。
    • これとは逆に、選択度の低い項目では不利になることが多い。
  • 選択度

    • 選択度が高い=重複が少ない
      (主キー、ユニーク キーなど)
    • 選択度が低い=重複が多い。
      (例えば、"男性"、"女性" というデータのみ格納する)

「非クラスタ化インデックス」と選択度

「非クラスタ化インデックス」は、選択度の低い項目に対しては不利である。

  • 例えば、"男性"、"女性" というデータのみ格納する項目に対して、
    「非クラスタ化インデックス」を作成し、1000 名の "男性" 社員を検索する時に
    「非クラスタ化インデックス」を使用して「インデックス スキャン」した場合を考える。

  • この場合、「非クラスタ化インデックス」では、
    「リーフ レベル ページ」の「インデックス ページ」から
    「データ ページ」にアクセスするため
    「データ ページ」に対して、最大で 1000 回もの I/O が発生する可能性がある。

「クラスタ化インデックス」と選択度

「クラスタ化インデックス」は、選択度の低い項目に対して "も" 有効である。

  • 例えば、"男性"、"女性" というデータのみ格納する項目に対して、
    「クラスタ化インデックス」を作成し、1000 名の "男性" 社員を検索する時に
    「クラスタ化インデックス」を使用して「インデックス スキャン」した場合を考える。

  • 「クラスタ化インデックス」を作成したテーブルでは、
    「クラスタ化キー」の値(この場合、"男性"、"女性")毎にデータがまとまっているため、

    • "男性" 社員情報を読み込むページ数は最小化され、I/O 回数も最小化される。
    • また、「非クラスタ化インデックス」と異なり、
      「リーフ レベル ページ」の「データ ページ」を直接スキャンすることができる。
  • 例えば、「データ ページ」に 10 レコードが格納できる場合、

    • 1000 名の "男性" 社員のレコードは 100 ページに格納され、
    • これが 1 つのエクステントに規則正しく格納されていれば、
    • 最小で 13 回の I/O で読み取りが完了する。

計算式

1000(レコード) / 10(レコード / ページ) / 8(ページ / エクステント) ≒ 13 エクステント
≒ 13 回の I/O

※ SQL Server は、ディスク I/O を、ディスク上管理単位である「エクステント」単位で処理する。

選択度とインデックスの「ページ分割」

なお、選択度の低いデータでは、どちらのインデックスでも、
データの挿入時に、「ページ分割」が発生しやすくなり、不利である。

「ページ分割」については、「「インデックスの断片化」の管理」で説明する。

選択度の低い項目をキーにした「クラスタ化インデックス」の作成は、

  • 検索(「範囲検索」・「順次アクセス」)の効率
  • データ更新時の「ページ分割」のオーバーヘッド

のトレードオフを考慮する形になる。

補足(選択度の低い列に対する現在の選択肢): 「性別」のような
選択度の低い列に単独でインデックスを張ることは、現在でも推奨されない。
ただし、以下は有効なことがある。

  • 複合インデックスの先頭以外に置く
    (部署ID, 性別) のように、選択度の高い列と組み合わせる)
  • フィルタ選択されたインデックス
    WHERE Status = 'Active' のように、少数派の値だけを対象にする)
  • 列ストア インデックス
    (重複が多い列ほど圧縮率が高く、集計クエリで威力を発揮する)

「インデックスの断片化」の管理

「インデックスの断片化」とは

DB の「データ ファイル」は、

  • 論理的な「セグメント」、
  • 物理的な「エクステント」

から構成される。

「セグメント」とは、テーブル、インデックスといった、オブジェクトを意味する。

SQL Server は、

  • ディスク I/O を、ディスク上管理単位である 64KB の「エクステント」単位で処理する。
  • また、「エクステント」は、メモリ上の管理単位である 8KB の「ページ」から構成される。

「セグメント」、「エクステント」、「ページ」

  • データの追加、更新処理などで、

    • 「インデックス ページ」、「データ ページ」内の空き領域が埋まった場合、
    • 「ページ分割」が発生し、一部の「ページ」が、
      別の「エクステント」に格納されることがある。
  • 例えば、SQL Server では

    • 「インデックス ページ」、「データ ページ」が埋まると、
      「ページ分割」により新しい行を挿入する余裕を作り出す。
    • この作業にはコストがかかるため、DB サーバ全体のパフォーマンスを低下させる。
      「インデックスの断片化」は、「インデックス ページ」、「データ ページ」の
      「ページ分割」が進んだ状態を指す。

インデックスの断片化(ページ分割が進んだ状態)

  • 「インデックスの断片化」が進んだ状態では、I/O 処理の連続性が失われ、
    別の「エクステント」から断片化した「ページ」を取得するという
    余分な I/O が発生する。

インデックスの断片化による余分なI/Oの発生

  • 一般的に、この状態はセグメント(テーブル、インデックス)を
    「再構築」することで解消できる。

補足(断片化の測り方と対処): 断片化の状況は以下で確認する。

SELECT
    OBJECT_NAME(ips.object_id) AS table_name,
    i.name                     AS index_name,
    ips.avg_fragmentation_in_percent,
    ips.avg_page_space_used_in_percent,
    ips.page_count
FROM sys.dm_db_index_physical_stats(
         DB_ID(), NULL, NULL, NULL, 'SAMPLED') AS ips
JOIN sys.indexes AS i
  ON i.object_id = ips.object_id AND i.index_id = ips.index_id
WHERE ips.page_count > 1000
ORDER BY ips.avg_fragmentation_in_percent DESC;

定番の判断基準は以下。

断片化率 対処
〜5% 何もしない
5〜30% ALTER INDEX ... REORGANIZE(オンライン、ログ消費が小さい)
30%〜 ALTER INDEX ... REBUILD(統計も更新される)

ただし、ページ数が少ないインデックス(1000 ページ未満が目安)は
断片化率が高く出ても無視してよい

また、SSD / NVMe ではシーク コストが無いため、
断片化による性能影響は HDD 時代より格段に小さい。
現在は「断片化率」より **avg_page_space_used_in_percent(ページ密度)**の
低下によるページ数の増加のほうが問題になりやすい。

なお、REBUILD のオンライン実行は
Enterprise Edition の機能(SQL Server 2016 以降は
RESUMABLE = ON による中断・再開も可能)。

「ページ密度」とは

  • 「ページ分割」は、

    • DB サーバ全体のパフォーマンスの低下や、
    • 「インデックスの断片化」による余分な I/O の発生に

    繋がる。このため、なるべく「ページ分割」が発生しないようにする必要がある。

  • 「ページ分割」の発生を抑止するため、

    • 更新と挿入が頻繁に行われる予定のテーブルや、インデックスには
      「ページ密度」を低く設定し、データの増加に対応する空き領域を残しておく。
    • 「ページ密度」は、テーブル、インデックスの生成時に設定することができる。
  • ただし、「ページ密度」の値が低いと、
    クエリを処理するために読み取るページ(エクステント)が多くなる可能性があるので、
    以下のトレードオフを考慮し、「ページ密度」を決定する必要がある。

    • 読み取り処理:読み取りページ(エクステント)数の増加
    • 書き込み処理:「ページ分割」の発生
  • 例えば、テーブルが読み取り専用で変更されない場合は、
    テーブルや、インデックスの「ページ密度」を高く設定することで、
    読み取りページ(エクステント)数を減らすことができる。

「ページ密度」の設定

「ページ密度」は、FILLFACTOR オプションで設定することができる。

「FILLFACTOR」オプション

  • FILLFACTOR は、

    • CREATE INDEX ステートメント
    • DBCC DBREINDEX ステートメント
    • DBCC INDEXDEFRAG ステートメント

    のオプションで指定できる。

  • このオプションは、

    • 「インデックス ページ」
    • 「データ ページ」

    の「ページ密度」を制御する。

  • 通常、既定の FILLFACTOR で適切なパフォーマンスが得られるが、
    場合によっては FILLFACTOR を変更することでさらにパフォーマンスが高まる。

補足(最新化): DBCC DBREINDEXDBCC INDEXDEFRAG
非推奨であり、現在は

ALTER INDEX IX_Name ON dbo.Table1 REBUILD WITH (FILLFACTOR = 90, ONLINE = ON);
ALTER INDEX IX_Name ON dbo.Table1 REORGANIZE;

を使用する。
なお、FILLFACTOR が効くのはインデックスの作成・再構築時のみで、
通常の挿入・更新には影響しない点に注意
(空き領域は再構築時に確保され、その後は埋まっていく)。
単調増加するクラスタ化キーには FILLFACTOR を下げても意味がない
(末尾に追記されるだけでページ分割が起きないため)。

「PAD_INDEX」オプション

  • PAD_INDEX は、CREATE INDEX のステートメントのオプションで指定できる。

  • このオプションは、インデックスの「リーフ レベル ページ」ではなく、
    インデックスの「中間レベル ページ」の「ページ密度」を制御する。

  • PAD_INDEXFILLFACTOR で指定されているパーセンテージを使用するので、
    PAD_INDEXFILLFACTOR が指定されている場合にのみ有効になる。

参考

複合インデックス

補足(インデックスが使われない典型パターン): 設計が正しくても、
クエリの書き方次第でインデックスは使われない(SARGable でない)。

NG な書き方 対処
WHERE YEAR(OrderDate) = 2026 WHERE OrderDate >= '2026-01-01' AND OrderDate < '2027-01-01'
WHERE col + 0 = @v / WHERE ISNULL(col,0) = @v 列に演算・関数を掛けない
WHERE col LIKE '%abc%' 前方一致('abc%')にする。中間一致は全文検索を検討
nvarchar 列に varchar の値を渡す 暗黙の型変換でスキャンになる。パラメータの型を揃える

最後の「暗黙の型変換」は、
ADO.NET のパラメータ型が列と食い違っている場合に起きやすく、
実行プランに CONVERT_IMPLICIT の警告として現れる
ADO.NETデータプロバイダの接続文字列
実行プランのグラフィカル表示参照)。


Tags: 移行, データアクセス, SQL Server

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally