it-swarm.com.de

Wie funktioniert Paging mit ROW_NUMBER in SQL Server?

Ich habe eine Employee -Tabelle mit einer Million Datensätzen. Ich habe folgende SQL für Paging-Daten in einer Webanwendung. Es funktioniert gut. Was ich jedoch als Problem sehe, ist - die abgeleitete Tabelle tblEmployee wählt alle Datensätze in der Tabelle Employee aus (um die MyRowNumber -Werte zu erstellen).

Ich denke, dies führt zur Auswahl aller Datensätze in der Tabelle Employee.

Funktioniert es wirklich so? Oder ist SQL Server so optimiert, dass auch nur die 5 Datensätze aus der ursprünglichen Employee -Tabelle ausgewählt werden?

DECLARE @Index INT;
DECLARE @PageSize INT;

SET @Index = 3;
SET @PageSize = 5;

SELECT *  FROM
  (SELECT  ROW_NUMBER() OVER (ORDER BY EmpID asc) as MyRowNumber,*
  FROM Employee) tblEmployee
WHERE MyRowNumber BETWEEN ( ((@Index - 1) * @PageSize )+ 1) AND @Index*@PageSize 
13
LCJ

Eine Alternative zum Testen könnte sein:

;WITH x AS (SELECT EmpID, k = ROW_NUMBER() OVER (ORDER BY EmpID) FROM dbo.Emp)
SELECT e.columns
FROM x INNER JOIN dbo.Emp AS e
ON x.EmpID = e.EmpID
WHERE x.k BETWEEN (((@Index - 1) * @PageSize) + 1) AND @Index * @PageSize
ORDER BY ...;

Ja, Sie haben die Tabelle zweimal getroffen, aber im CTE, in dem Sie die gesamte Tabelle scannen, greifen Sie nur nach dem Schlüssel, nicht nach ALLEN Daten. Aber Sie sollten sich diesen Artikel unbedingt ansehen:

http://www.sqlservercentral.com/articles/T-SQL/66030/

Und die anschließende Diskussion:

http://www.sqlservercentral.com/Forums/Topic672980-329-1.aspx

In SQL Server 2012 können Sie natürlich die neue Syntax OFFSET/FETCH NEXT Verwenden:

;WITH x AS 
(
  SELECT EmpID FROM dbo.Emp
    ORDER BY EmpID
    OFFSET  @PageSize * (@Index - 1) ROWS
    FETCH NEXT @PageSize ROWS ONLY
)
SELECT e.columns
FROM x INNER JOIN dbo.Emp AS e
ON x.EmpID = e.EmpID
ORDER BY ...; 

Darüber habe ich auch hier ausführlicher gebloggt:

18
Aaron Bertrand

Obwohl Sie den Mechanismus dahinter möglicherweise nicht kennen, können Sie dies selbst testen, indem Sie die Leistung Ihrer Abfrage vergleichen mit: Wählen Sie * aus Mitarbeiter.

Die neueren Versionen von SQL Server leisten gute Arbeit bei der Optimierung, können jedoch von mehreren Faktoren abhängen.

Wie Ihre ROW_NUMBER-Funktion funktioniert, hängt von der Order By-Klausel ab. In Ihrem Beispiel würden die meisten vermuten, dass EmpID der Primärschlüssel ist.

Es gibt einige where -Klauseln, die so komplex und/oder schlecht codiert oder indiziert sind, dass Sie möglicherweise besser den gesamten Datensatz zurückgeben sollten (dies ist selten und kann behoben werden). Die Verwendung von ZWISCHEN hat Probleme.

Bevor Sie davon ausgehen, dass es besser ist, alle Zeilen an Ihre Anwendung zurückzugeben und es herauszufinden, sollten Sie an der Optimierung Ihrer Abfrage arbeiten. Überprüfen Sie die Schätzungen. Fragen Sie den Query Analyzer. Testen Sie einige Alternativen.

2
JeffO

Ich weiß, dass die Frage sich auf row_number () bezieht, aber ich möchte eine neue Funktion von SQL Server 2012 hinzufügen. In SQL Server 2012 wird als nächstes die neue Funktion OFFSET Fetch eingeführt, die sehr schnell ist als row_number (). Ich habe es benutzt und es gibt mir ein gutes Ergebnis, hoffe ihr füllt auch die gleiche Erfahrung.

Ich habe ein Beispiel unter http://blogfornet.com/2013/06/sql-server-2012-offset-use/ gefunden

das ist nützlich. Hoffe, es wird Ihnen auch bei der Implementierung neuer Funktionen helfen ...

2
Sam Raj