Ai-je besoin de séparer les index pour chaque type de requête, ou sera un travail d'index à plusieurs colonnes?

dba.stackexchange https://dba.stackexchange.com/questions/197

  •  16-10-2019
  •  | 
  •  

Question

Je sais un peu la réponse à cette question déjà, mais je me sens toujours comme si il y a plus j'ai besoin de revenir sur le sujet.

Ma compréhension de base est que d'une manière générale, un seul indice qui comprend seulement tous les champs que vous pourriez listez / trier à tout moment donné n'est pas susceptible d'être utile, mais je l'ai vu ce genre de chose. Comme, quelqu'un a pensé: « Eh bien, si nous venons de mettre tout ce genre de choses dans un index, la base de données peut l'utiliser pour trouver ce dont il a besoin », sans avoir jamais vu un plan d'exécution pour certains des requêtes réelles en cours d'exécution.

Imaginez une table comme ceci:

id int pk/uid
name varchar(50)
customerId int (foreign key)
dateCreated datetime

Je pourrais voir un index unique, y compris les champs name, customerId et dateCreated.

Mais je crois comprendre qu'un tel indice ne serait pas utilisé dans une requête comme, par exemple:

SELECT [id], [name], [customerId], [dateCreated]
   FROM Representatives WHERE customerId=1 
   ORDER BY dateCreated

Pour la requête telle, il me semble qu'une meilleure idée serait un indice incluant les champs de customerId et dateCreated, avec le champ customerId étant « première ». Cela créerait un indice qui aurait les données organisées en manière telle que cette requête pourrait trouver rapidement ce dont il a besoin -. Dans l'ordre qu'il a besoin

Une autre chose que je vois, peut-être aussi souvent que le premier, est index individuels sur chaque champ; ainsi, une sur chacun des champs name, customerId et dateCreated.

Contrairement au premier exemple, ce type d'arrangement me semble parfois être au moins partiellement utile; Le plan d'exécution de la requête peut montrer qu'au moins il utilise l'index sur la customerId pour sélectionner les enregistrements, mais il ne l'utilise l'index avec le champ dateCreated pour les trier.


Je sais que c'est une grande question, car la réponse spécifique à une requête particulière sur un ensemble particulier de tables est généralement de voir ce que le plan d'exécution dit qu'il va faire, et par ailleurs prendre les spécificités de la table (s) et les requêtes en compte. Aussi, je sais que cela dépend de la fréquence à laquelle une requête peut être exécutée par opposition à la charge de maintenir un indice particulier pour elle.

Mais je suppose que ce que je demande est en général « point de départ » pour les index, fait l'idée d'avoir des indices de spécifiques pour spécifiques, les requêtes fréquemment élongations et les champs de la WHERE ou ORDER BY clauses de sens?

Était-ce utile?

La solution

Vous avez raison que votre exemple de requête ne serait pas utiliser cet indice.

Le planificateur de requêtes envisager d'utiliser un index si:

  • tous les champs qu'il contient sont référencés dans la requête
  • quelques-uns des champs à partir du début sont référencés

Il ne sera pas en mesure d'utiliser les index qui commencent par un champ non utilisé par la requête.

Donc, pour votre exemple:

SELECT [id], [name], [customerId], [dateCreated]
   FROM Representatives WHERE customerId=1 
   ORDER BY dateCreated

il envisagerait des indices tels que:

[customerId]
[customerId], [dateCreated]
[customerId], [dateCreated], [name]

mais pas:

[name], [customerId], [dateCreated]

Si elle trouve à la fois [customerId] et [customerId], [dateCreated], [name] sa décision de préférer l'un sur l'autre dépendra des statistiques de l'indice qui dépendent des estimations de la balance des données dans les champs. Si [customerId], [dateCreated] ont été définis il faut préférer que sur les deux autres à moins que vous donner un indice spécifique indice contraire.

Il est pas rare de voir un index défini pour chaque champ dans mon expérience non plus, bien que ce soit rarement optimale que la gestion supplémentaire nécessaire pour mettre à jour les index sur insertion / mise à jour et l'espace supplémentaire nécessaire pour les stocker, est perdu quand la moitié d'entre eux ne peut jamais se habituer -. mais à moins que votre DB voit les charges d'écriture lourde la performance ne va pas puer mal même avec les indices excès

index spécifiques pour les requêtes fréquentes qui seraient autrement lents en raison de la table ou le balayage d'index est généralement une bonne idée, mais de ne pas trop que vous pourriez échangez un problème de performance pour une autre. Si vous ne définissez [customerId], [dateCreated] comme un indice, par exemple, rappelez-vous que le planificateur de requêtes sera en mesure d'utiliser pour les requêtes qui utiliseraient un index sur [customerId] si elle est présente. Tout en utilisant juste [customerId] serait légèrement plus efficace que d'utiliser l'indice composé ce peut être atténué par se retrouver avec deux indices en compétition pour l'espace dans la RAM au lieu d'un (mais si facilement l'ensemble de votre fits jeu de travail normale dans la RAM ce concours de mémoire supplémentaire ne peut pas être un problème).

Autres conseils

Pour répondre à votre question initiale, oui, les index doivent être conçus autour de la requêtes , non seulement le Tableau . Ordre des champs de l'index est d'une importance vitale. La conception d'un seul index pour être optimal pour plusieurs requêtes est plus difficile, et vous devrez faire des compromis.

En ce qui concerne votre deuxième point, oui, un tas d'indices sur les champs individuels simples est fâcheusement commune. Je vois tout le temps dans mon environnement, et son me habituellement un drapeau rouge que l'équipe de développement n'a pas travaillé avec un DBA pour concevoir des index appropriés.

Ma stratégie pour les index de conception, est à l'index:

  • Les champs utilisés dans WHERE (dans l'ordre de sélectivité)
  • Les champs utilisés dans ORDER BY
  • Inclure d'autres champs (si nécessaire) pour faire un index de couverture

Donc, pour votre exemple:

SELECT [id], [name], [customerId], [dateCreated]
   FROM Representatives WHERE customerId=1 
   ORDER BY dateCreated

Je probablement concevoir un index sur (CustomerID, dateCreated) Include (id, nom). Cet indice couvre signifie que la requête n'a jamais frapper la table d'origine, ce qui améliore grandement les performances.

Cet exemple est presque aussi simple, cependant. Un indice naïf juste (CustomerID) remplirait presque aussi bien (en supposant que chaque client a un seul représentant, alors qu'une recherche unique de signet à la table sera nécessaire). Il a également pourrait même être bénéfique pour réellement faire une en cluster index (CustomerID, ID), en fonction de ce que les autres requêtes exécutées sur la table.

Licencié sous: CC-BY-SA avec attribution
Non affilié à dba.stackexchange
scroll top