Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

moyen efficace d'implémenter la pagination

Essayer de vous donner une réponse brève à votre doute, si vous exécutez le skip(n).take(m) méthodes sur linq (avec SQL 2005/2008 comme serveur de base de données), votre requête utilisera le Select ROW_NUMBER() Over ... instruction, avec en quelque sorte une pagination directe dans le moteur SQL.

En vous donnant un exemple, j'ai une table db appelée mtcity et j'ai écrit la requête suivante (fonctionne aussi avec linq to entity):

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

La requête résultante sera :

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]

Qui est un accès aux données fenêtré (plutôt cool, d'ailleurs parce que vous renverrez des données depuis le tout début et accéderez à la table tant que les conditions sont remplies). Ce sera très similaire à :

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

À l'exception de cela, cette deuxième requête sera exécutée plus rapidement que le résultat linq car elle utilisera exclusivement l'index pour créer la fenêtre d'accès aux données ; cela signifie que si vous avez besoin d'un filtrage, le filtrage doit être (ou doit être) dans la liste des entités (où la ligne est créée) et certains index doivent également être créés pour maintenir les bonnes performances.

Maintenant, quoi de mieux ?

Si vous avez un flux de travail assez solide dans votre logique, la mise en œuvre de la méthode SQL appropriée sera compliquée. Dans ce cas, LINQ sera la solution.

Si vous pouvez abaisser cette partie de la logique directement à SQL (dans une procédure stockée), ce sera encore mieux car vous pouvez implémenter la deuxième requête que je vous ai montrée (en utilisant des index) et permettre à SQL de générer et de stocker le plan d'exécution du requête (amélioration des performances).