Ich habe Log- und LogItem-Tabellen. Ich schreibe eine Abfrage, um einige Daten von beiden zu erfassen. Es gibt Tausende von Logs
und jeder Log
kann 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 where
Klauseln 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.
quelle
Antworten:
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 = something
sie verstreut sind, da sie zu verschiedenen Werten voncolumn1
und gehörencolumn2
. Aber wenn Sie es wissencolumn1
undcolumn2
auch wissen , ist es ein Kinderspiel, den richtigen Zweig im Baum zu finden.quelle
where
s können sich überlappen, sodass Sie möglicherweise einen Index haben, der mehrerewhere
s gut abdeckt . oder Sie können einen Teil einerwhere
Klausel ignorieren , da die Indizierung für eine bestimmte Spalte sowieso nicht hilfreich ist (geringe Selektivität). aber im großen und ganzen ja.where
Klauseln 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 erforderlichenwhere
Spalten als erste Spalten enthält.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
ParentLogID
und suchenDatabaseModified
, 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) .quelle
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 = 3
Index(a,b,c,d)
... WHERE A IN (...) AND D = 5
Index(a,d)