Sollten sich die Filterspalten immer in den Schlüsseln / Includes befinden?

8

Ich denke darüber nach, einen gefilterten Index in meiner Kopie der Stack Overflow-Datenbank zu erstellen . So etwas zum Beispiel:

CREATE UNIQUE NONCLUSTERED INDEX IX_DisplayName_Filtered
    ON dbo.Users (DisplayName)
    WHERE Reputation > 400000;

Sollte ich die Spalte im Filterausdruck ( Reputationin diesem Beispiel) immer zum Schlüssel hinzufügen oder für den Index einschließen, oder ist es gut genug, sie im Filterausdruck zu haben?

Josh Darnell
quelle

Antworten:

10

Ja!

Aus verschiedenen Gründen ist es immer besser, die Filterspalte als Teil des Index zu haben: entweder in den Schlüsseln oder in den Includes

Im Folgenden finden Sie einige spezifische Beispiele für Probleme mit gefilterten Indexabfragen, die durch Einfügen der Filterspalten in den Index behoben werden.

Schlüsselsuche, wenn das Abfrageprädikat nicht mit dem Filterausdruck übereinstimmt

Zuallererst enthält die Dokumentation Folgendes zum Einfügen von Filterausdrucksspalten:

  • Eine Spalte im gefilterten Indexausdruck sollte ein Schlüssel oder eine enthaltene Spalte in der gefilterten Indexdefinition sein, wenn das Abfrageprädikat die Spalte in einem Vergleich verwendet, der nicht dem gefilterten Indexausdruck entspricht.

Wenn Sie also einen Ungleichheitsfilterausdruck wie haben Reputation > 400000, Ihre Abfrage jedoch ein Prädikat wie verwendet WHERE Reputation > 400000 AND Reputation < 450000;, wird der gefilterte Index möglicherweise weiterhin verwendet. Es ist jedoch eine Schlüsselsuche erforderlich, um das Prädikat der Abfrage zu erfüllen.

Durch das Einfügen der ReputationSpalte in den Index (Schlüssel oder Includes) ist diese Suche nicht mehr erforderlich.

Weitere Details und ein Beispiel für diese Situation finden Sie in Erik Darlings Beitrag Gefilterte Indizes: Just Add Includes .

Ein weiteres Beispiel hierfür finden Sie in Paul Whites Antwort hier: Unnötige Schlüsselsuche unter Verwendung des gefilterten Index

Schlüsselsuche, wenn die Filterspalte in der Ergebnismenge enthalten ist

In der Dokumentation heißt es weiter:

  • Eine Spalte im gefilterten Indexausdruck sollte ein Schlüssel oder eine enthaltene Spalte in der gefilterten Indexdefinition sein, wenn sich die Spalte in der Abfrageergebnismenge befindet.

Dies mag sich selbstverständlich anfühlen, aber nur um vollständig zu sein: Wenn Ihre Abfragen die Filterspalte in der endgültigen Ergebnismenge enthalten, sollten Sie sie wahrscheinlich in den Index aufnehmen (Schlüssel oder Includes).

Schlechte Zeilenschätzungen bei Verwendung von Gleichheitsausdrücken

Es gibt Fälle, in denen nützliche Zeilenschätzungen basierend auf tatsächlichen Statistiken während des Optimierungsprozesses eliminiert werden können (insbesondere wenn der vom Optimierer erstellte Abfrageplan in einen physischen Ausführungsplan konvertiert wird). Durch das Einschließen der Filterspalte kann verhindert werden, dass diese genaueren Schätzungen verworfen werden.

Weitere Details und ein Beispiel finden Sie in Paul Whites Antwort hier: Falsche Zeilenschätzung mit einem gefilterten Index

Ein weiteres Beispiel finden Sie hier auf dba.se: Abfrage mit einem gefilterten Index, aber falsch geschätzter Zeilenanzahl

Schlüsselsuche bei Verwendung IS NULLim Filterausdruck

Das Erstellen eines Index mit einem Filterausdruck, der verwendet wird, IS NULLkann zu einer völlig unnötigen Schlüsselsuche führen. Siehe diese Frage und den zugehörigen Fehlerbericht auf der Feedback-Site von SQL Server: Warum wird der gefilterte Index für den IS NULL-Wert nicht verwendet?

Wie Sie vielleicht erraten haben, besteht die Problemumgehung darin, die Filterspalte als eingeschlossene Spalte in den gefilterten Index einzufügen.

Josh Darnell
quelle