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

effiziente Methode zur Implementierung von Paging

Ich versuche, Ihnen eine kurze Antwort auf Ihren Zweifel zu geben, wenn Sie skip(n).take(m) ausführen Methoden auf linq (mit SQL 2005 / 2008 als Datenbankserver) verwendet Ihre Abfrage die Select ROW_NUMBER() Over ... -Anweisung, mit irgendwie direktem Paging in der SQL-Engine.

Um Ihnen ein Beispiel zu geben:Ich habe eine DB-Tabelle namens mtcity und ich habe die folgende Abfrage geschrieben (funktioniert auch mit Linq to Entities):

using (DataClasses1DataContext c = new DataClasses1DataContext())
{
    var query = (from MtCity2 c1 in c.MtCity2s
                select c1).Skip(3).Take(3);
    //Doing something with the query.
}

Die resultierende Abfrage lautet:

SELECT [t1].[CodCity], 
    [t1].[CodCountry], 
    [t1].[CodRegion], 
    [t1].[Name],  
    [t1].[Code]
FROM (
    SELECT ROW_NUMBER() OVER (
        ORDER BY [t0].[CodCity], 
        [t0].[CodCountry], 
        [t0].[CodRegion], 
        [t0].[Name],
        [t0].[Code]) AS [ROW_NUMBER], 
        [t0].[CodCity], 
        [t0].[CodCountry], 
        [t0].[CodRegion], 
        [t0].[Name],
        [t0].[Code]
    FROM [dbo].[MtCity] AS [t0]
    ) AS [t1]
WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p0 + @p1
ORDER BY [t1].[ROW_NUMBER]

Das ist ein Datenzugriff mit Fenster (ziemlich cool, übrigens, weil Daten von Anfang an zurückgegeben werden und auf die Tabelle zugegriffen wird, solange die Bedingungen erfüllt sind). Dies wird sehr ähnlich sein zu:

With CityEntities As 
(
    Select ROW_NUMBER() Over (Order By CodCity) As Row,
        CodCity //here is only accessed by the Index as CodCity is the primary
    From dbo.mtcity
)
Select [t0].[CodCity], 
        [t0].[CodCountry], 
        [t0].[CodRegion], 
        [t0].[Name],
        [t0].[Code]
From CityEntities c
Inner Join dbo.MtCity t0 on c.CodCity = t0.CodCity
Where c.Row Between @p0 + 1 AND @p0 + @p1
Order By c.Row Asc

Mit der Ausnahme, dass diese zweite Abfrage schneller ausgeführt wird als das linq-Ergebnis, da ausschließlich der Index verwendet wird, um das Datenzugriffsfenster zu erstellen. Das bedeutet, wenn Sie eine Filterung benötigen, sollte (oder muss) die Filterung in der Entitätsliste (wo die Zeile erstellt wird) und einige Indizes sollten ebenfalls erstellt werden, um die gute Leistung aufrechtzuerhalten.

Nun, was ist besser?

Wenn Sie einen ziemlich soliden Workflow in Ihrer Logik haben, wird die Implementierung des richtigen SQL-Wegs kompliziert. In diesem Fall ist LINQ die Lösung.

Wenn Sie diesen Teil der Logik direkt auf SQL (in einer gespeicherten Prozedur) absenken können, ist dies sogar noch besser, da Sie die zweite Abfrage, die ich Ihnen gezeigt habe, implementieren können (unter Verwendung von Indizes) und SQL erlauben, den Ausführungsplan der zu generieren und zu speichern Abfrage (Verbesserung der Leistung).