Warum hat das Erstellen dieses neuen Index die Leistung so verbessert, wenn der vorhandene Index alle Spalten im neuen Index enthielt?

19

Ich habe Log- und LogItem-Tabellen. Ich schreibe eine Abfrage, um einige Daten von beiden zu erfassen. Es gibt Tausende von Logsund jeder Logkann bis zu 125 habenLogItems

Die fragliche Abfrage ist kompliziert, daher überspringe ich sie (wenn jemand der Meinung ist, dass es wichtig ist, dass ich sie veröffentlichen kann). Als ich den Plan für geschätzte SSMS-Abfragen ausführte, wurde mir jedoch mitgeteilt, dass ein neuer nicht geclusterter Index die Leistung um bis zu 100% verbessern würde. .

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

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

Aus Spaß habe ich diesen neuen Index erstellt und die Abfrage ausgeführt. Zu meiner großen Überraschung dauert es jetzt ca. 1 Sekunde, bis meine Abfrage ausgeführt wird. Früher waren es mehr als 10 Sekunden.

Ich bin davon ausgegangen, dass mein vorhandener Index diese neue Abfrage abdecken würde. Meine Frage ist also, warum das Erstellen eines neuen Index für die einzigen in meiner neuen Abfrage verwendeten Spalten die Leistung verbessert hat. Sollte ich für jede in meinen whereKlauseln verwendete eindeutige Spaltenkombination einen Index haben ?

Hinweis: Ich glaube nicht, dass dies daran liegt, dass der SQL Server meine Ergebnisse zwischenspeichert. Ich habe die Abfrage ungefähr 25 bis 30 Mal ausgeführt, bevor ich den Index erstellt habe, und es dauerte durchgehend 10 bis 15 Sekunden, nachdem der Index nun durchgehend ~ 1 ist oder weniger.

Nate
quelle
Was wurde im tatsächlichen Ausführungsplan für die Indexverwendung angezeigt, bevor Sie den zusätzlichen nicht gruppierten Index erstellt haben ?
Thomas Stringer
Was ist eine um 100% verbesserte Leistung?
@ Hai Gute Frage, ich bin nicht sicher. Dies ist meine erste Performance-Debugging-Situation. Ich werde das in Zukunft auf jeden Fall in den Griff bekommen. Alles, was es sagte, war "Fehlender Index" und es sagte, welche Felder.
@JeffO Dies ist, was SSMS sagte: "Der Abfrageprozessor schätzt, dass die Implementierung des folgenden Index die Abfragekosten um 100% verbessern könnte."

Antworten:

21

Die Reihenfolge der Spalten in einem Index ist wichtig. Wenn für das Filtern die Spalten 1 und 4 aus dem Index erforderlich sind, hilft der Index nicht weiter. Dies ist nur nützlich, wenn nach den ersten N aufeinander folgenden Spalten gefiltert wird.

Dies liegt daran, dass der Index ein Baum ist. Sie können nicht alle Knoten des Baums effizient auswählen, an denen column3 = somethingsie verstreut sind, da sie zu verschiedenen Werten von column1und gehören column2. Aber wenn Sie es wissen column1und column2auch wissen , ist es ein Kinderspiel, den richtigen Zweig im Baum zu finden.

GSerg
quelle
Wäre es dann sicher anzunehmen, dass ich (im Allgemeinen) einen Index pro Satz von "where" -Klauseln benötige, die diese Tabelle treffen werden?
Ich habe einmal die Abfrage einer anderen Person massiv beschleunigt, indem ich sichergestellt habe, dass der Index in der richtigen Reihenfolge verwendet wird.
1
@Nate Im Großen und Ganzen ja. Einige wheres können sich überlappen, sodass Sie möglicherweise einen Index haben, der mehrere wheres gut abdeckt . oder Sie können einen Teil einer whereKlausel ignorieren , da die Indizierung für eine bestimmte Spalte sowieso nicht hilfreich ist (geringe Selektivität). aber im großen und ganzen ja.
@Nate Sie möchten nicht mehr Indizes als nötig haben. Jeder Index, den SQL verwalten muss, fügt einen eigenen Overhead hinzu. Wenn Sie Ihre WHERE-Klauseln so neu anordnen können, dass sie mit den ersten N Spalten in einem vorhandenen Index übereinstimmen, sollten Sie dies sehr genau tun, ohne zusätzliche Indizes hinzuzufügen.
Das Chuck Guy
1
@ChuckBlumreich Die Reihenfolge der Spalten in whereKlauseln ist nicht wichtig. Der Server wird sie immer so einrichten, dass vorhandene Indizes optimal genutzt werden. Es geht nur darum, einen Index zu haben, der alle erforderlichen whereSpalten als erste Spalten enthält.
12

Auf die Vorderkante eines Index kommt es an.

Solange Ihre Abfrage von einer führenden Kante eines Index abgedeckt wird, ist sie effizient. Datenbankindizes werden in der Regel als B-Bäume implementiert, und die Struktur des B-Baums gibt vor, dass die Suche in einer bestimmten Reihenfolge erfolgen muss. Aus diesem Grund ist die Reihenfolge der Felder im zusammengesetzten Index von Bedeutung.

Wenn Sie "Löcher" haben, z. B. wenn Sie nach ParentLogIDund suchen DatabaseModified, aber nur einen Index haben {ParentLogID, DateModified, Name, DatabaseModified}, kann nur der {ParentLogID}Teil des Index effizient genutzt werden.

(Hinweis: Einige DBMSes können den nutzen {DatabaseModified}Teil durch „Skip - Scan“, aber selbst wenn Ihr DBMS tut , dass es viel weniger effizient als der reguläre Indexzugriff ist) .

Branko Dimitrijevic
quelle
Wenn ich also einen guten Index habe Columns (a, b, c, d, e, f)und die meisten Abfragen sind , hilft es nicht, wenn ich einen habe , weshalb der neue Index, den ich erstellt habe, die Leistung so stark verbessert hat, oder? ... WHERE A IN(...) AND B = 3Index(a,b,c,d)... WHERE A IN (...) AND D = 5Index(a,d)
8
@Nate - richtig. Stellen Sie es sich wie ein Telefonbuch vor. Wenn Sie nur den Vornamen von jemandem kennen, ist es unmöglich zu finden, ohne das ganze Buch durchzusehen, da es nach Nachnamen, Vorname
JNK