2008-10-04 9 views
5

EDIT:Ich warte immer noch auf weitere Antworten. Vielen Dank!Was ist eine effiziente Methode zum Paging durch sehr große Ergebnismengen in SQL Server 2005?

In SQL 2000 Tagen habe ich Temptabelle Methode zu verwenden, in dem Sie eine temporäre Tabelle mit neuen Identitätsspalte und Primärschlüssel erstellen Sie dann wählen, wo Identitätsspalte zwischen A und B.

Wenn SQL 2005 kam entlang ich fand heraus über Row_Number() und ich benutze es seitdem ...

Aber jetzt fand ich ein ernstes Leistungsproblem mit Row_Number(). Es funktioniert sehr gut, wenn Sie mit nicht-gigantischen Resultsets arbeiten und eine Identitätsspalte sortieren. Allerdings es führt sehr schlecht, wenn Sie mit arbeiten große Ergebnissätze wie über 10.000 Datensätze und Sortierung über nicht Identität Spalte. Row_Number() funktioniert schlecht, auch wenn Sie nach einer Identitätsspalte sortieren, wenn die Ergebnismenge über 250.000 Datensätze beträgt. Für mich kam es zu einem Punkt, wo es einen Fehler wirft, „Befehl Timeout!

Was Sie Paginieren eine große Ergebnismenge auf SQL 2005 zu tun verwenden? Ist die temporäre Tabellenmethode in diesem Fall noch besser? Ich bin nicht sicher, ob diese Methode besser funktioniert ... Aber einige sagen, dass es ein Problem gibt, eine falsche Zeilennummer zu geben, wenn Sie einen mehrspaltigen Primärschlüssel haben.

In meinem Fall muss ich in der Lage sein, die Ergebnismenge durch eine Datumsspalte für meine Produktions-Web-App zu sortieren.

Lassen Sie mich wissen, was Sie für leistungsstarke Paginierung in SQL 2005 verwenden. Und ich würde auch gerne eine clevere Möglichkeit kennen, Indizes zu erstellen. Ich vermute, dass die Wahl der richtigen Primärschlüssel und/oder Indizes (Clustered/Non-Clustered) eine große Rolle spielen wird.

Vielen Dank im Voraus.

P.S. Weiß jemand, was Stackoverflow verwendet?

EDIT:-Mine sieht ungefähr so ​​aus ...

SELECT postID, postTitle, postDate 
FROM 
    (SELECT postID, postTitle, postDate, 
     ROW_NUMBER() OVER(ORDER BY postDate DESC, postID DESC) as RowNum 
    FROM MyTable 
    ) as DerivedMyTable 
WHERE RowNum BETWEEN @startRowIndex AND (@startRowIndex + @maximumRows) - 1 

postID: Int, Identität (Autoinkrement), Primärschlüssel

nachdatieren: Datetime

EDIT: Verwenden alle Row_Number()?

Antwort

0

Nun, für Ihre Beispielabfrage sollte ROW_COUNT ziemlich schnell mit Tausenden von Zeilen sein, vorausgesetzt, Sie haben einen Index für Ihr PostDate-Feld. Ist dies nicht der Fall, muss der Server einen kompletten Clustered-Index-Scan auf Ihrem PK durchführen, praktisch jede Seite laden, Ihr PostDate-Feld abrufen, danach sortieren, die zu extrahierenden Zeilen für das Resultset ermitteln und diese Zeilen erneut abrufen. Es wird immer wieder ein temporärer Index erstellt (möglicherweise wird in der Ebene ein Tabellen-/Index-Spool angezeigt).

Kein Wunder, dass Sie Timeouts bekommen.

Mein Vorschlag: einen Index für nachdatieren DESC gesetzt, ist es das, was ROW_NUMBER geht über - (ORDER BY nachdatieren DESC, ...)

Wie für den Artikel, den Sie sich beziehen - ich habe recht getan viel Paging und Sachen mit SQL Server 2000 in der Vergangenheit ohne ROW_COUNT und der in diesem Artikel verwendete Ansatz ist der effizienteste. Es funktioniert nicht unter allen Umständen (Sie benötigen eindeutige oder fast eindeutige Werte). Ein Überblick über einige andere Methoden ist here.

.

7

Die Methode row_number() sollte schnell sein. Ich habe gute Ergebnisse für 100.000 Zeilen gesehen.

Sie verwenden row_number() ähnlich dem folgenden:

SELECT column_list 
FROM 
    (SELECT column_list 
     ROW_NUMBER() OVER(ORDER BY OrderByColumnName) as RowNum 
    FROM MyTable m 
    ) as DerivedTableName 
WHERE RowNum BETWEEN @startRowIndex AND (@startRowIndex + @maximumRows) - 1 

... und machen Sie einen abdeckenden Index für die column_list und/oder einen Index auf der Spalte 'OrderByColumnName'?

+0

Vielen Dank für Ihre Eingabe. Ich habe meine Frage aktualisiert. –