web-dev-qa-db-ja.com

インデックスに列を含めるための厳格な規則

非クラスター化インデックスに含まれる列に含める列と順序を決定するための厳格な規則はありますか?私はこの投稿を読んでいただけです https://stackoverflow.com/questions/1307990/why-use-the-include-clause-when-creating-an-index そして、次のクエリでそれを見つけました:

SELECT EmployeeID, DepartmentID, LastName
FROM Employee
WHERE DepartmentID = 5

ポスターはこのように索引を作ることを提案しました:

CREATE NONCLUSTERED INDEX NC_EmpDep 
  ON Employee(EmployeeID, DepartmentID)
  INCLUDE (Lastname)

ここに私の質問が来ます、なぜこのようにインデックスを作成できないのですか?

CREATE NONCLUSTERED INDEX NC_EmpDep 
      ON Employee( EmployeeID, DepartmentID, LastName)

または

    CREATE NONCLUSTERED INDEX NC_EmpDep 
          ON Employee( EmployeeID, LastName)
INCLUDE (DepartmentID)

そして、LastName列を含めたままにすることを決定するようにポスターを導くものは何か。なぜ他のカラムではないのですか?そして、列をそこに保持する必要がある順序をどのように決定するのですか?

38
Rocky Singh

Marc_sによるそのインデックスの提案は間違っています。コメントを追加しました。 (そして、私の答えも受け入れられました!)

このクエリのインデックスは

CREATE NONCLUSTERED INDEX NC_EmpDep 
  ON Employee(DepartmentID)
  INCLUDE (Lastname, EmployeeID)

インデックスは通常

CREATE INDEX <name> ON <table> (KeyColList) INCLUDE (NonKeyColList)

どこ:

  • KeyColList =キー列=行の制限と処理に使用
    WHERE、JOIN、ORDER BY、GROUP BYなど
  • NonKeyColList =非キー列=選択/制限後のSELECTおよび集計(SUM(col)など)で使用
48
gbn

JNKとgbnは素晴らしい答えを出しましたが、単一のクエリだけに焦点を当てるのではなく、全体像を検討する価値もあります。この特定のクエリはインデックス(#1)の恩恵を受ける可能性がありますが、

Employee(DepartmentID) INCLUDE (Lastname, EmployeeID)

このインデックスは、クエリが次のようにわずかに変更された場合はまったく役に立ちません。

SELECT EmployeeID, DepartmentID, LastName
FROM Employee
WHERE DepartmentID = 5 AND LastName = 'Smith'

これにはインデックスが必要です(#2):

Employee(DepartmentID, LastName) INCLUDE (EmployeeID)

部門5に1,000人の従業員がいるとします。含まれる列はキーの一部ではないため、インデックス#1を使用してすべてのスミスを見つけるには、部門5の1,000行すべてをシークする必要があります。インデックス#2を使用すると、部門5のLastName Smithを直接検索できます。

したがって、インデックス#2はより広い範囲のクエリを処理するのに役立ちますが、コストはより膨らんだインデックスキーになるため、インデックスの非リーフページが大きくなります。システムはそれぞれ異なるため、ここでは経験則はありません。


補足として、EmployeeIDがこのテーブルのクラスタリングキーである場合(クラスタ化インデックスを想定)、EmployeeIDを含める必要はありません。これは、すべての非クラスタ化インデックスに存在します。つまり、インデックス#2は、なる

Employee(DepartmentID, LastName)
19
Jim McLeod

どうやって最初のものを手に入れたのか分かりません。私にとって、そのクエリでは、次のように使用します。

CREATE NONCLUSTERED INDEX NC_EmpDep 
  ON Employee(DepartmentID)
  INCLUDE (EmployeeID, Lastname)

SQLのほとんど何にも「厳格な規則」はありません。

ただし、例では、インデックスがDepartmentID句にあるため、インデックスが使用する唯一のフィールドはWHEREです。

他のフィールドはそこから簡単にアクセスできる必要があります。 DepartmentIDに基づいて選択すると、INCLUDEには、インデックスのリーフノードにこれらのフィールドがあります。

他の例はこのインデックスでは機能しないため、使用しないでください。

インデックスを電話帳のようなものと考えてください。ほとんどの電話帳は、姓、名、ミドルネームの順になっています。電話帳のインデックスの順序に基づいて名を検索することができないため、誰かの姓は知っているが姓は知らない場合、電話帳は役に立ちません。

INCLUDEフィールドは、電話番号、住所など、書籍の各エントリのその他の情報に似ています。

編集:

使用しない理由をさらに明確にするには:

CREATE NONCLUSTERED INDEX NC_EmpDep 
          ON Employee( EmployeeID, LastName)
INCLUDE (DepartmentID)

このインデックスは、EmployeeID句にEmployeeIDまたは[〜#〜] both [〜#〜]LastNameおよびWHEREがある場合にのみ役立ちます。これは、このクエリに必要なものの[〜#〜] opposite [〜#〜]とほぼ同じです。

7
JNK

(employee_id、department_id)インデックスは引き続き使用できると思いますが、whereフレーズに「ダミー」行を含める必要があります。例: "employee_id = employee_id)

  • (employee_id、departemnent_id)にインデックスがある
  • department_idのみを検索/制限する必要がある
  • 間違った順序でインデックスが使用されないことを知っている(または、今では物事が変更されており、次の「トリック」はもう必要ありません。私は「古い」ですか?)
  • 「古い」トリックを使用しますか?

    従業員の従業員から*を選択します
    where emp.employee_id = emp.employee_id
    およびemp.department_id = 5

(したがって、ここではラストネームのインクルード部分に焦点を当てていませんが、はい/またはキーが使用されていないことに焦点を当てています。)

敬具、

ミゲル

0
Miguel Leeuwe