web-dev-qa-db-fra.com

Règle dure et rapide pour inclure des colonnes dans l'index

Existe-t-il une règle stricte pour décider quelles colonnes et dans quel ordre elles doivent être placées Inclus dans un index non clusterisé? Je viens de lire ce post https://stackoverflow.com/questions/1307990/why-use-the-include-clause-when-creating-an-index et je l'ai trouvé pour la requête suivante :

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

L'affiche a suggéré de faire un index comme celui-ci:

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

voici ma question pourquoi ne pouvons-nous pas faire un index comme celui-ci

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

ou

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

et ce qui amène l'affiche à décider de conserver la colonne LastName incluse. Pourquoi pas d'autres colonnes? et comment décider dans quel ordre nous devons y conserver les colonnes?

38
Rocky Singh

Cette suggestion d'index par marc_s est fausse. J'ai ajouté un commentaire. (Et c'était ma réponse acceptée aussi!)

L'index de cette requête serait

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

Un index est généralement

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

Où:

  • KeyColList = Colonnes clés = utilisées pour la restriction et le traitement des lignes
    O JOIN REJOINDRE, COMMANDER PAR, GROUPER PAR etc.
  • NonKeyColList = Colonnes non clés = utilisées dans SELECT et agrégation (par exemple SUM (col)) après sélection/restriction
48
gbn

JNK et gbn ont donné d'excellentes réponses, mais cela vaut également la peine de considérer la situation dans son ensemble - pas seulement de se concentrer sur une seule requête. Bien que cette requête particulière puisse bénéficier d'un index (# 1):

Employee(DepartmentID) INCLUDE (Lastname, EmployeeID)

Cet index n'aide pas du tout si la requête change légèrement, comme:

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

Cela aurait besoin de l'index (# 2):

Employee(DepartmentID, LastName) INCLUDE (EmployeeID)

Imaginez que vous comptiez 1 000 employés dans le département 5. À l'aide de l'index n ° 1, pour trouver tous les Smiths, vous devez parcourir les 1 000 lignes du département 5, car les colonnes incluses ne font pas partie de la clé. En utilisant l'index n ° 2, vous pouvez rechercher directement le département 5, LastName Smith.

L'index n ° 2 est donc plus utile pour répondre à un plus large éventail de requêtes - mais le coût est une clé d'index plus gonflée, ce qui augmentera la taille des pages non foliaires de l'index. Chaque système sera différent, il n'y a donc pas de règle générale ici.


En remarque, il convient de souligner que si EmployeeID était la clé de clustering pour cette table - en supposant un index clusterisé - alors vous n'avez pas besoin d'inclure EmployeeID - il est présent dans tous les index non clusterisés, ce qui signifie que l'index # 2 pourrait simplement être

Employee(DepartmentID, LastName)
19
Jim McLeod

Je ne sais pas comment vous avez obtenu ce premier. Pour moi, pour cette requête, j'utiliserais:

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

Il n'y a pas de "règle stricte et rapide" pour à peu près tout dans SQL.

Mais, pour votre exemple, le seul champ que l'index utilisera est DepartmentID car il se trouve dans la clause WHERE.

Les autres champs doivent simplement être facilement accessibles à partir de là. Vous sélectionnez en fonction de DepartmentID puis le INCLUDE a ces champs au nœud feuille de l'index.

Vous ne voulez pas utiliser vos autres exemples car ils ne fonctionneraient pas pour cet index.

Pensez à un index comme un annuaire téléphonique. La plupart des annuaires téléphoniques sont classés par nom, prénom, initiale du deuxième prénom. Si vous connaissez le prénom de quelqu'un, mais pas son nom de famille, l'annuaire téléphonique ne vous sert à rien car vous ne pouvez pas rechercher le prénom en fonction de l'ordre de l'index de l'annuaire téléphonique.

Les champs INCLUDE sont comme le numéro de téléphone, l'adresse, etc. d'autres informations pour chaque entrée du livre.

MODIFIER:

Pour clarifier davantage pourquoi ne pas utiliser:

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

Cet index n'est utile que si vous avez EmployeeID ou LES DEUX EmployeeID et LastName dans votre WHERE clause. C'est à peu près le OPPOSÉ de ce dont vous avez besoin pour cette requête.

7
JNK

Je pense que vous pourriez toujours être en mesure d'utiliser l'index (employee_id, department_id), mais vous devrez inclure une ligne "factice" dans la phrase where, comme: "employee_id = employee_id)

  • avoir un index sur (employee_id, departemnent_id),
  • avoir à rechercher/restreindre uniquement sur un département_id
  • sachant qu'il n'utilisera pas l'index depuis un mauvais ordre (ou que les choses ont changé maintenant, et le "truc" suivant n'est plus nécessaire. Je suis un "vieux"?) .
  • Utilisez le "vieux" tricK?

    sélectionnez * dans Employé emp
    emp.employee_id = emp.employee_id
    et emp.department_id = 5

(Je ne me concentre donc pas sur la partie d'inclusion ici de Lastname, mais sur le oui/ou non de la clé.)

Sincères amitiés,

Miguell

0
Miguel Leeuwe