Was soll ich tun, um einen Clustered Index Seek anstelle von Clustered Index Scan zu erhalten?

7

Ich habe eine Stored Procedure in SQL Server 2005, und wenn ich es ausführe und ich mir den Ausführungsplan anschaue, merke ich, dass es einen Clustered-Index-Scan macht, und das kostet ihn 84%. Ich habe gelesen, dass ich einige Dinge ändern muss, um einen Clustered Index Seek zu bekommen, aber ich weiß nicht, was ich ändern soll.

Ich werde jede Hilfe mit diesem schätzen.

Danke,

Brian

    
Brian Roisentul 31.08.2009, 21:42
quelle

2 Antworten

19

Ohne jedes Detail ist es schwer zu erraten, was das Problem ist und ob es überhaupt ein Problem ist. Die Wahl eines Scans anstelle einer Suche könnte durch viele Faktoren gesteuert werden:

  • Die Abfrage drückt eine Ergebnismenge aus, die die gesamte Tabelle abdeckt. Ie. Die Abfrage ist eine einfache SELECT * FROM <table> . Dies ist ein trivialer Fall, der perfekt durch einen Index-Scan mit Clustern abgedeckt wäre, ohne dass etwas anderes in Betracht gezogen werden müsste.
  • Der Optimierer hat keine Alternativen:
    • Die Abfrage drückt eine Teilmenge der gesamten Tabelle aus, aber das Filterprädikat bezieht sich auf Spalten, die nicht Teil des gruppierten Schlüssels sind, und für diese Spalten gibt es auch keine nicht-verschleierten Indizes. Dies ist kein alternativer Plan außer einem vollständigen Scan.
    • Die Abfrage enthält Filterprädikate für Spalten im clustred-Indexschlüssel, sie sind jedoch nicht SARGable . Das Filterprädikat muss normalerweise neu geschrieben werden, um es SARGable zu machen, das korrekte Neuschreiben hängt von Fall zu Fall ab. Ein subtileres Problem kann aufgrund impliziter Konvertierungsregeln auftreten, z. Das Filterprädikat ist WHERE column = @value , aber die Spalte ist VARCHAR (Ascii) und @value ist NVARCHAR (Unicode).
    • Die Abfrage enthält SARGale-Filterprädikate für Spalten im gruppierten Schlüssel, aber die Spalte ganz links wird nicht gefiltert. Ie. Der clustred-Index befindet sich in den Spalten (foo, bar) , die WHERE-Klausel befindet sich jedoch nur in bar .
  • Der Optimierer wählt einen Scan aus.
    • Wenn die Alternative ein nicht gruppierter Index ist, dann scannen (oder Bereichssuche), aber die Wahl ist, um den gruppierten Index zu verwenden, kann die Ursache normalerweise bis auf Index-Tipping-Punkt aufgrund des Mangels an Nicht-Clustered-Index-Abdeckung für die Abfrage-Projektion. Beachten Sie, dass dies nicht Ihre Frage ist, da Sie einen Clustered-Index-Suchvorgang und keinen nicht-fehlerhaften Index-Suchvorgang erwarten (die Frage ist zu 100% genau und dokumentiert ...)
    • Kardinalitätsschätzungen. Die Abfragekalkulation basiert auf der Clustered-Index-Schlüsselstatistik, die eine Schätzung der Kardinalität des Ergebnisses liefert (dh wie viele Zeilen übereinstimmen). Bei einer einfachen Abfrage Dies kann nicht passieren, da jede Schätzung für eine Such- oder Bereichssuche niedriger ist als die für einen Scan, unabhängig von der Statistik, aber für eine komplexe -Abfrage mit Joins und Filter für mehrere Tabellen, die Dinge sind komplexer und der Plan kann einen Scan enthalten, bei dem eine Suche erwartet wurde, weil der Abfrageoptimierer einen Plan wählen kann, bei dem die Join-Bewertungsreihenfolge umgekehrt wird, was der Beobachter erwartet. Die Wahl der umgekehrten Reihenfolge kann (meistens) korrigiert werden oder kann problematisch sein (normalerweise aufgrund von veralteten Statistiken oder Parameter-Sniffing).
    • Eine Bestellgarantie. Ein Scan erzeugt Ergebnisse in einer garantierten Reihenfolge und Elemente, die höher im Ausführungsbaum sind, können von dieser Reihenfolge profitieren (z. B. kann eine Sortierung oder ein Spool eliminiert werden, oder ein Merge-Join kann anstelle von Hash / verschachtelten Joins verwendet werden). Insgesamt sind die Abfragekosten besser, da der Zugriffspfad scheinbar langsamer ist.

Dies sind einige schnelle Hinweise, warum ein Clustered-Index-Scan vorhanden sein kann, wenn eine Clustered-Index-Suche erwartet wird. Die Frage ist extrem generisch und es ist unmöglich, eine Antwort "warum" zu geben, außer sich auf einen 8-Ball zu verlassen. Nun, wenn ich Ihre Frage richtig dokumentiert und korrekt artikuliert habe, bedeutet dies, dass Sie einen eindeutigen Datensatz basierend auf einem clustered Schlüsselwert suchen, um einen Clustered Index seek zu erwarten. In diesem Fall muss das Problem mit der SARGability der WHERE-Klausel gelöst werden.

    
Remus Rusanu 31.08.2009, 22:59
quelle
5

Wenn die Abfrage mehr als einen bestimmten Prozentsatz der Zeilen in der Tabelle einbezieht, wählt das Optimierungsprogramm einen Scan statt einer Suche aus, da es vorhersagt, dass es in diesem Fall weniger Festplatten-IOs benötigt ( Für jede Zeile, die es zurückgibt, benötigt es im Index einen Datenträger-E / A pro Ebene. Für einen Suchvorgang gibt es in der gesamten Tabelle nur einen Datenträger-E / A pro Zeile.

Wenn also beispielsweise im b-tree-Index 5 Ebenen vorhanden sind, ist es günstiger, die gesamte Tabelle zu lesen, wenn die Abfrage mehr als 20% der Zeilen in der Tabelle generiert, als 5 IOs für jede der Zeilen zu erstellen die 20% Zeilen ...

Können Sie die Ausgabe der Abfrage etwas eingrenzen, um die Anzahl der Zeilen zu reduzieren, die von diesem Schritt zurückgegeben werden? Das würde ihm helfen, die Suche über den Scan zu wählen.

    
Charles Bretana 31.08.2009 21:49
quelle