Pourquoi la création de ce nouvel index a-t-elle tellement amélioré les performances alors que l'index existant incluait toutes les colonnes dans le nouvel index?

19

J'ai des tables Log et LogItem; J'écris une requête pour récupérer des données des deux. Il y en a des milliers Logset chacun Logpeut en avoir jusqu'à 125LogItems

La requête en question est compliquée, donc je la saute (si quelqu'un pense que c'est important, je peux probablement la poster), mais lorsque j'ai exécuté le plan SSMS Estimated Query, il m'a dit qu'un nouvel index non clusterisé améliorerait les performances jusqu'à 100%. .

Existing Index: Non-clustered
Key Colums (LogItem): ParentLogID, DateModified, Name, DatabaseModified

Query Plan Recommendation
CREATE NONCLUSTERED INDEX [LogReportIndex]
ON [dbo].[LogItem] ([ParentLogID],[DatabaseModified])

Juste pour le plaisir, j'ai créé ce nouvel index et exécuté la requête et à ma grande surprise, il faut maintenant environ 1 seconde pour que ma requête s'exécute, alors qu'elle était avant 10+ secondes.

J'ai supposé que mon index existant couvrirait cette nouvelle requête, donc ma question est pourquoi la création d'un nouvel index sur les seules colonnes utilisées dans ma nouvelle requête a-t-elle amélioré les performances? Dois-je avoir un index pour chaque combinaison unique de colonnes utilisée dans mes whereclauses?

note: Je ne pense pas que ce soit parce que SQL Server met en cache mes résultats, j'ai exécuté la requête environ 25-30 fois avant de créer l'index et cela a pris régulièrement 10-15 secondes, après l'index, il est maintenant uniformément ~ 1 ou moins.

Nate
la source
Avant de créer l'index non cluster supplémentaire, que montrait le plan d'exécution réel pour l'utilisation de l'index?
Thomas Stringer
Qu'est-ce qu'une performance améliorée de 100%?
@ Shark Bonne question, je ne suis pas sûr. Il s'agit de ma première situation de débogage de performances. Je serai sûr de saisir cela à l'avenir. Tout ce qu'il a dit était «Index manquant» et il a indiqué quels champs.
@JeffO Voici ce qu'a dit SSMS: "Le processeur de requêtes estime que l'implémentation de l'index suivant pourrait améliorer le coût des requêtes de 100%."

Réponses:

21

L'ordre des colonnes dans un index est important. Si le filtrage nécessite les colonnes 1 et 4 de l'index, l'index ne va pas aider. Il n'est utile que lors du filtrage par les N premières colonnes consécutives.

C'est parce que l'index est un arbre. Vous ne pouvez pas sélectionner efficacement tous les nœuds de l'arbre où column3 = something, parce qu'ils sont dispersés tous les autres, appartenant à différentes valeurs de column1et column2. Mais si vous le savez column1et column2aussi, localiser la bonne branche dans l'arbre est une évidence.

GSerg
la source
Serait-il alors prudent de supposer (en général) que j'ai besoin d'un index par ensemble de clauses "where" qui vont frapper cette table?
Une fois, j'ai fait une accélération massive de la requête de quelqu'un d'autre juste en m'assurant qu'il utilisait l'index dans le bon ordre.
1
@Nate En gros, oui. Certains wheres peuvent se chevaucher, vous pouvez donc avoir un index qui couvre bien plusieurs wheres; ou vous pouvez ignorer une partie d'une whereclause car l'indexation sur une certaine colonne ne va pas aider de toute façon (faible sélectivité); mais en gros, oui.
@Nate Vous ne voulez pas avoir plus d'index que nécessaire. Chaque index que SQL doit maintenir ajoute des frais généraux qui lui sont propres. Si vous pouvez réorganiser vos clauses WHERE pour qu'elles correspondent aux N premières colonnes d'un index existant, cela devrait vous rapprocher sans ajouter d'index supplémentaires.
Ce Chuck Guy
1
@ChuckBlumreich L'ordre des colonnes dans les whereclauses n'est pas important. Le serveur les organisera toujours pour utiliser au mieux les index existants. Il s'agit seulement d'avoir un index qui inclut toutes les wherecolonnes requises comme premières colonnes.
12

Le bord avant d'un indice est ce qui compte.

Tant que votre requête est "couverte" par un bord d'attaque d'un index, elle sera efficace. Les index de base de données sont généralement implémentés en tant qu'arbres B et la structure de l'arbre B impose que la recherche doit être effectuée dans un certain ordre, c'est pourquoi l'ordre des champs dans l'index composite est important.

Si vous avez des "trous", par exemple si vous effectuez une recherche sur ParentLogIDet DatabaseModified, mais que seul l'index est activé {ParentLogID, DateModified, Name, DatabaseModified}, alors seule la {ParentLogID}partie de l'index peut être utilisée efficacement.

(REMARQUE: certains SGBD peuvent utiliser la {DatabaseModified}partie via "skip scan", mais même si votre SGBD le fait, il est beaucoup moins efficace que l'accès à l'index normal) .

Branko Dimitrijevic
la source
Donc, si j'ai Columns (a, b, c, d, e, f)et la plupart des requêtes sont ... WHERE A IN(...) AND B = 3mon index Index(a,b,c,d)qui est bon, mais cela n'aide pas si j'ai, ... WHERE A IN (...) AND D = 5c'est pourquoi mon nouvel index que j'ai fait, a Index(a,d)tellement amélioré les performances, non?
8
@Nate - correct. Pensez-y comme un annuaire téléphonique. Si vous ne connaissez que le prénom de quelqu'un, il est impossible de le trouver sans parcourir l'intégralité du livre, car il est organisé sur Nom, Prénom
JNK