Das OFFSET ... FETCH
mit SQL Server 2012 eingeführte neue Modell bietet einfaches und schnelleres Paging. Warum gibt es überhaupt Unterschiede, wenn man bedenkt, dass die beiden Formen semantisch identisch und sehr häufig sind?
Man würde annehmen, dass der Optimierer beide erkennt und sie (trivial) vollständig optimiert.
Hier ist ein sehr einfacher Fall, in OFFSET ... FETCH
dem der Kostenvoranschlag ~ 2x schneller ist.
SELECT * INTO #objects FROM sys.objects
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY object_id) r
FROM #objects
) x
WHERE r >= 30 AND r < (30 + 10)
ORDER BY object_id
SELECT *
FROM #objects
ORDER BY object_id
OFFSET 30 ROWS FETCH NEXT 10 ROWS ONLY
Sie können diesen Testfall variieren, indem Sie ein CI erstellen object_id
oder Filter hinzufügen. Es ist jedoch unmöglich, alle Planunterschiede zu entfernen. OFFSET ... FETCH
ist immer schneller, weil es zur Ausführungszeit weniger Arbeit macht.
Antworten:
Die Beispiele in der Frage führen nicht zu den gleichen Ergebnissen (das
OFFSET
Beispiel weist einen Fehler von eins auf). Die aktualisierten Formulare unten beheben dieses Problem, entfernen die zusätzliche Sortierung für denROW_NUMBER
Fall und verwenden Variablen, um die Lösung allgemeiner zu gestalten:Der
ROW_NUMBER
Plan hat geschätzte Kosten von 0.0197935 :Der
OFFSET
Plan hat geschätzte Kosten von 0.0196955 :Dies entspricht einer Einsparung von 0,000098 geschätzten Kosteneinheiten (obwohl der
OFFSET
Plan zusätzliche Operatoren erfordern würde, wenn Sie eine Zeilennummer für jede Zeile zurückgeben möchten). DerOFFSET
Plan wird im Allgemeinen immer noch etwas billiger sein, aber denken Sie daran, dass die geschätzten Kosten genau so hoch sind - echte Tests sind immer noch erforderlich. Der Großteil der Kosten in beiden Plänen sind die Kosten für die gesamte Art der Eingabemenge, sodass hilfreiche Indizes beiden Lösungen zugute kommen würden.Wenn konstante
OFFSET 30
Literalwerte verwendet werden (z. B. im ursprünglichen Beispiel), kann der Optimierer eine TopN-Sortierung anstelle einer vollständigen Sortierung gefolgt von einer Top-Sortierung verwenden. Wenn die für die TopN-Sortierung benötigten Zeilen ein konstantes Literal sind und <= 100 (die Summe vonOFFSET
undFETCH
), kann die Ausführungsengine einen anderen Sortieralgorithmus verwenden, der eine schnellere Leistung als die verallgemeinerte TopN-Sortierung liefert. Alle drei Fälle weisen insgesamt unterschiedliche Leistungsmerkmale auf.Wie, warum sich der Optimierer nicht automatisch die Transformation
ROW_NUMBER
Syntax Muster zu verwendenOFFSET
, gibt es eine Reihe von Gründen:OFFSET
wird nicht garantiert, dass der Plan in allen Fällen besser istEin Beispiel für den dritten Punkt oben ist, dass der Paging-Satz ziemlich breit ist. Es kann wesentlich effizienter sein , die benötigten Schlüssel mit einem nicht gruppierten Index zu suchen und manuell nach dem gruppierten Index zu suchen , als den Index mit
OFFSET
oder zu durchsuchenROW_NUMBER
. Es sind weitere Probleme zu berücksichtigen, wenn die Paging-Anwendung wissen muss, wie viele Zeilen oder Seiten insgesamt vorhanden sind. Es ist auch eine gute Diskussion über die Vorzüge des ‚Schlüssel suchen‘ und ‚Offset‘ Methoden hier .Insgesamt ist es wahrscheinlich besser
OFFSET
, wenn die Benutzer eine fundierte Entscheidung treffen, ihre Paging-Abfragen gegebenenfalls nach gründlichen Tests zu ändern .quelle
Mit ein wenig Fummeln an Ihrer Anfrage bekomme ich die gleichen Kosten Kostenschätzung (50/50) und gleich IO - Statistik:
Dies vermeidet die zusätzliche Art , das erscheint in Ihrer Version , indem Sie auf das Sortieren
r
stattobject_id
.quelle
r
anstatt nach der Basisspalte zu sortieren, wenn auch nur, weil es mit dem übereinstimmt, was ich in einer nicht verschachtelten Abfrage und nach einem Ausdruck tun würde. Ich würde den dem Ausdruck zugewiesenen Alias verwenden, anstatt den Ausdruck zu wiederholen.Sie haben das Abfrageoptimierungsprogramm geändert, um diese Funktion hinzuzufügen. Das heißt, sie haben Mechanismen implementiert, die speziell den Befehl offset ... fetch unterstützen. Mit anderen Worten, für die Top-Abfrage muss SQL Server viel mehr Arbeit leisten. Also der Unterschied in den Abfrageplänen.
quelle