Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Optimieren von SQL-Abfragen durch Entfernen des Sortieroperators im Ausführungsplan

Zuerst sollten Sie überprüfen, ob die Sortierung tatsächlich ein Leistungsengpass ist. Die Dauer der Sortierung hängt von der Anzahl der zu sortierenden Elemente ab, und die Anzahl der Speicher für einen bestimmten übergeordneten Speicher ist wahrscheinlich klein. (Das setzt voraus, dass der Sortieroperator angewendet wird, nachdem die where-Klausel angewendet wurde).

Das ist eine Überverallgemeinerung. Oft kann ein Sortieroperator einfach in den Index verschoben werden und kann, wenn nur die ersten paar Zeilen der Ergebnismenge abgerufen werden, die Abfragekosten erheblich reduzieren, da die Datenbank nicht mehr alle übereinstimmenden Zeilen abrufen (und sortieren muss all), um die ersten zu finden, kann aber die Datensätze in der Reihenfolge der Ergebnismenge lesen und stoppen, sobald genügend Datensätze gefunden wurden.

In Ihrem Fall scheinen Sie die gesamte Ergebnismenge abzurufen, sodass eine Sortierung die Dinge wahrscheinlich nicht viel schlimmer machen wird (es sei denn, die Ergebnismenge ist riesig). Außerdem ist es in Ihrem Fall möglicherweise nicht trivial, einen nützlichen sortierten Index zu erstellen, da die where-Klausel ein or enthält.

Wenn Sie diesen Sortieroperator immer noch loswerden möchten, können Sie Folgendes versuchen:

SELECT [Phone]
FROM [dbo].[Store]
WHERE [ParentStoreId] = 10
AND [Type] in (0, 1)
ORDER BY [Phone]    

Alternativ können Sie den folgenden Index versuchen:

CREATE NONCLUSTERED INDEX IX_Store ON dbo.[Store]([ParentStoreId], [Phone], [Type])

um zu versuchen, den Abfrageoptimierer dazu zu bringen, einen Indexbereichsscan für ParentStoreId durchzuführen scannen Sie dann alle übereinstimmenden Zeilen im Index und geben Sie sie aus, wenn Type Streichhölzer. Dies führt jedoch wahrscheinlich zu mehr Festplatten-E/A und verlangsamt daher Ihre Abfrage, anstatt sie zu beschleunigen.

Bearbeiten :Als letzten Ausweg könnten Sie

verwenden
SELECT [Phone]
FROM [dbo].[Store]
WHERE [ParentStoreId] = 10
AND [Type] = 0
ORDER BY [Phone]

UNION ALL

SELECT [Phone]
FROM [dbo].[Store]
WHERE [ParentStoreId] = 10
AND [Type] = 1
ORDER BY [Phone]

mit

CREATE NONCLUSTERED INDEX IX_Store ON dbo.[Store]([ParentStoreId], [Type], [Phone])

und sortieren Sie die beiden Listen auf dem Anwendungsserver, wo Sie (wie beim Mergesort) die vorsortierten Listen zusammenführen können, wodurch eine vollständige Sortierung vermieden wird. Aber das ist wirklich eine Mikrooptimierung, die zwar die Sortierung selbst um eine Größenordnung beschleunigt, sich aber wahrscheinlich nicht stark auf die Gesamtausführungszeit der Abfrage auswirkt, da ich davon ausgehe, dass der Engpass Netzwerk- und Festplatten-E/A ist. insbesondere im Hinblick auf die Tatsache, dass die Festplatte viele wahlfreie Zugriffe durchführt, da der Index nicht geclustert ist.