Was ist der beste Weg (in Bezug auf die Leistung), um Ergebnisse in SQL Server 2000, 2005, 2008, 2012 zu paginieren, wenn Sie auch die Gesamtzahl der Ergebnisse (vor dem Paginieren) erhalten möchten?
sql
sql-server
performance
pagination
Panagiotis Korros
quelle
quelle
Antworten:
Das Abrufen der Gesamtzahl der Ergebnisse und das Paginieren sind zwei verschiedene Vorgänge. Nehmen wir für dieses Beispiel an, dass es sich bei der Abfrage handelt, mit der Sie sich befassen
In diesem Fall würden Sie die Gesamtzahl der Ergebnisse ermitteln mit:
... was ineffizient erscheinen mag, aber tatsächlich ziemlich performant ist, vorausgesetzt, alle Indizes usw. sind ordnungsgemäß eingerichtet.
Um die tatsächlichen Ergebnisse auf ausgelagerte Weise wiederherzustellen, ist die folgende Abfrage am effizientesten:
Dadurch werden die Zeilen 1 bis 19 der ursprünglichen Abfrage zurückgegeben. Das Coole dabei, insbesondere für Web-Apps, ist, dass Sie außer den zurückzugebenden Zeilennummern keinen Status beibehalten müssen.
quelle
Schließlich wurde Microsoft SQL Server 2012 veröffentlicht. Ich mag die Einfachheit einer Paginierung sehr. Sie müssen keine komplexen Abfragen verwenden, wie sie hier beantwortet wurden.
Um die nächsten 10 Zeilen zu erhalten, führen Sie einfach diese Abfrage aus:
https://docs.microsoft.com/en-us/sql/t-sql/queries/select-order-by-clause-transact-sql#using-offset-and-fetch-to-limit-the-rows- ist zurückgekommen
Wichtige Punkte, die bei der Verwendung zu beachten sind:
ORDER BY
ist obligatorisch, umOFFSET ... FETCH
Klausel zu verwenden .OFFSET
Klausel ist obligatorisch mitFETCH
. Sie können nicht verwendenORDER BY ... FETCH
.TOP
kann nicht mitOFFSET
undFETCH
im selben Abfrageausdruck kombiniert werden .quelle
LISTAGG()
/GROUP_CONCAT()
.FOR XML
: stackoverflow.com/a/273330/429949FOR XML PATH ('')
. Erstens werden XML-Steuerzeichen durch XML-Entitätscodes ersetzt. Hoffe , dass Sie nicht haben<
,>
oder&
in Ihren Daten! ZweitensFOR XML PATH ('')
wird auf diese Weise tatsächlich eine undokumentierte Syntax verwendet. Sie sollten eine benannte Spalte oder einen alternativen Elementnamen angeben. Beides nicht zu tun ist nicht im Dokument enthalten, was bedeutet, dass das Verhalten unzuverlässig ist. Drittens, je mehr wir die fehlerhafteFOR XML PATH ('')
Syntax akzeptieren, desto weniger wahrscheinlich ist es, dass MS tatsächlich eine echteLISTAGG() [ OVER() ]
Funktion bereitstellt, wie sie benötigt wird.Unglaublicherweise hat keine andere Antwort den schnellsten Weg zur Paginierung in allen SQL Server-Versionen erwähnt. Offsets können für große Seitenzahlen furchtbar langsam sein, wie hier verglichen . Es gibt eine völlig andere, viel schnellere Möglichkeit, die Paginierung in SQL durchzuführen. Dies wird oft als "Suchmethode" oder "Keyset-Paginierung" bezeichnet, wie in diesem Blog-Beitrag hier beschrieben .
Das "Suchprädikat"
Die Werte
@previousScore
und@previousPlayerId
sind die jeweiligen Werte des letzten Datensatzes von der vorherigen Seite. Auf diese Weise können Sie die "nächste" Seite abrufen. Wenn dieORDER BY
Richtung istASC
, verwenden Sie>
stattdessen einfach .Mit der obigen Methode können Sie nicht sofort zu Seite 4 springen, ohne zuvor die vorherigen 40 Datensätze abgerufen zu haben. Aber oft will man sowieso nicht so weit springen. Stattdessen erhalten Sie eine viel schnellere Abfrage, mit der Daten je nach Indizierung möglicherweise in konstanter Zeit abgerufen werden können. Außerdem bleiben Ihre Seiten "stabil", unabhängig davon, ob sich die zugrunde liegenden Daten ändern (z. B. auf Seite 1, während Sie sich auf Seite 4 befinden).
Dies ist der beste Weg, um die Paginierung zu implementieren, wenn beispielsweise mehr Daten in Webanwendungen verzögert geladen werden.
Beachten Sie, dass die " Suchmethode " auch als Keyset-Paginierung bezeichnet wird .
Gesamtzahl der Datensätze vor der Paginierung
Mit der
COUNT(*) OVER()
Fensterfunktion können Sie die Anzahl der Gesamtdatensätze "vor der Paginierung" zählen. Wenn Sie SQL Server 2000 verwenden, müssen Sie auf zwei Abfragen für das zurückgreifenCOUNT(*)
.quelle
OFFSET .. FETCH
oder mit früherenROW_NUMBER()
Tricks implementieren .RowNumber
gibt mir konsistente 10 Elemente pro Seite. [3] Es funktioniert nicht mit vorhandenen Gittern, diepagenumber
und annehmenpagesize
.Ab SQL Server 2012 können wir
OFFSET
undFETCH NEXT
Clause verwenden, um die Paginierung zu erreichen.Versuchen Sie dies für SQL Server:
TechNet: Paging einer Abfrage mit SQL Server
quelle
MSDN: ROW_NUMBER (Transact-SQL)
quelle
Unter http://www.codeproject.com/KB/aspnet/PagingLarge.aspx finden Sie einen guten Überblick über verschiedene Paging-Techniken
Ich habe die ROWCOUNT-Methode ziemlich oft verwendet, meistens mit SQL Server 2000 (funktioniert auch mit 2005 und 2008, nur die Leistung im Vergleich zu ROW_NUMBER messen), sie ist blitzschnell, aber Sie müssen sicherstellen, dass die sortierten Spalten (meistens) haben ) eindeutige Werte.
quelle
Für SQL Server 2000 können Sie ROW_NUMBER () mithilfe einer Tabellenvariablen mit einer IDENTITY-Spalte simulieren:
Dieser Ansatz kann auf Tabellen mit mehrspaltigen Schlüsseln erweitert werden und verursacht keinen Leistungsaufwand bei der Verwendung von OR (wodurch die Indexverwendung übersprungen wird). Der Nachteil ist die Menge an temporärem Speicherplatz, der verbraucht wird, wenn der Datensatz sehr groß ist und sich einer in der Nähe der letzten Seite befindet. Ich habe die Cursorleistung in diesem Fall nicht getestet, aber es könnte besser sein.
Beachten Sie, dass dieser Ansatz für die erste Datenseite optimiert werden kann. Außerdem wurde ROWCOUNT verwendet, da TOP in SQL Server 2000 keine Variable akzeptiert.
quelle
Der beste Weg zum Paging in SQL Server 2012 ist die Verwendung von Offset und Fetch Next in einer gespeicherten Prozedur. OFFSET-Schlüsselwort - Wenn wir den Offset mit der order by-Klausel verwenden, überspringt die Abfrage die Anzahl der Datensätze, die wir in OFFSET n Rows angegeben haben.
FETCH NEXT-Schlüsselwörter - Wenn wir Fetch Next nur mit einer order by-Klausel verwenden, wird die Anzahl der Zeilen zurückgegeben, die beim Paging angezeigt werden sollen. Ohne Offset generiert SQL einen Fehler. Hier ist das folgende Beispiel.
Sie können es wie folgt ausführen.
quelle
Dies sind meine Lösungen zum Auslagern des Abfrageergebnisses auf der SQL Server-Seite. Diese Ansätze unterscheiden sich zwischen SQL Server 2008 und 2012. Außerdem habe ich das Konzept des Filterns und Ordnens nach einer Spalte hinzugefügt. Es ist sehr effizient, wenn Sie in Ihrem Gridview blättern, filtern und bestellen.
Vor dem Testen müssen Sie eine Beispieltabelle erstellen und eine Zeile in diese Tabelle einfügen: (In der realen Welt müssen Sie die Where-Klausel unter Berücksichtigung Ihrer Tabellenfelder ändern, und möglicherweise haben Sie im Hauptteil von select eine Verknüpfung und Unterabfrage.)
In all diesen Beispielen möchte ich 200 Zeilen pro Seite abfragen und rufe die Zeile für die Seitenzahl 1200 ab.
In SQL Server 2008 können Sie das CTE-Konzept verwenden. Aus diesem Grund habe ich zwei Arten von Abfragen für SQL Server 2008+ geschrieben
- SQL Server 2008+
Und zweite Lösung mit CTE in SQL Server 2008+
- SQL Server 2012+
quelle
Versuchen Sie diesen Ansatz:
quelle
In Bezug auf den Anwendungsfall scheint Folgendes einfach und schnell zu sein. Stellen Sie einfach die Seitenzahl ein.
auch ohne CTE
quelle
Nun, ich habe die folgende Beispielabfrage in meiner SQL 2000-Datenbank verwendet, sie funktioniert auch gut für SQL 2005. Die Leistung, die es Ihnen gibt, wird dynamisch geordnet, indem mehrere Spalten verwendet werden. Ich sage dir ... das ist mächtig :)
Der beste Teil ist, dass sp_executesql spätere Aufrufe zwischenspeichert, vorausgesetzt, Sie übergeben dieselben Parameter, dh Sie generieren denselben SQL-Text.
quelle
startet idx neu, wenn es um verschiedene init_id geht
quelle
ROW_NUMBER
Wenn Sie für die Technik keine zu verwendende Sortierspalte haben, können SieCURRENT_TIMESTAMP
Folgendes verwenden:Dies hat bei Suchvorgängen über Tabellengrößen von bis zu 700.000 gut funktioniert.
Dies holt Datensätze 11 bis 30.
quelle
quelle
Mit diesem Bit können Sie mit SQL Server und neueren Versionen von MySQL paginieren und die Gesamtzahl der Zeilen in jeder Zeile übertragen. Verwendet Ihren Pimary-Schlüssel, um die Anzahl der eindeutigen Zeilen zu zählen.
quelle
Dies ist ein Duplikat der alten SO-Frage von 2012: Effiziente Implementierung von Paging
Hier wird das Thema ausführlicher und mit alternativen Ansätzen diskutiert.
quelle
Ab 2012 können wir verwenden
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY
quelle
Sie haben weder die Sprache noch den von Ihnen verwendeten Treiber angegeben. Deshalb beschreibe ich es abstrakt.
quelle