Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

modo efficiente per implementare il paging

Cercando di darti una breve risposta al tuo dubbio, se esegui skip(n).take(m) metodi su linq (con SQL 2005 / 2008 come server di database) la tua query utilizzerà il Select ROW_NUMBER() Over ... istruzione, con è in qualche modo il paging diretto nel motore SQL.

Facendo un esempio, ho una tabella db chiamata mtcity e ho scritto la seguente query (funziona anche con linq to entità):

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 query risultante sarà:

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]

Che è un accesso ai dati con finestra (abbastanza interessante, a proposito, perché restituirà i dati sin dall'inizio e accederà alla tabella purché le condizioni siano soddisfatte). Sarà molto simile a:

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

Con l'eccezione che, questa seconda query verrà eseguita più velocemente del risultato linq perché utilizzerà esclusivamente l'indice per creare la finestra di accesso ai dati; questo significa che, se hai bisogno di alcuni filtri, il filtro dovrebbe essere (o deve essere) nell'elenco delle Entità (dove viene creata la riga) e dovrebbero essere creati anche alcuni indici per mantenere il buon rendimento.

Ora, cosa c'è di meglio?

Se hai un flusso di lavoro praticamente solido nella tua logica, l'implementazione del corretto modo SQL sarà complicato. In tal caso LINQ sarà la soluzione.

Se puoi abbassare quella parte della logica direttamente a SQL (in una procedura memorizzata), sarà ancora meglio perché puoi implementare la seconda query che ti ho mostrato (usando gli indici) e consentire a SQL di generare e memorizzare il Piano di esecuzione del query (miglioramento delle prestazioni).