sql >> Databáze >  >> RDS >> Sqlserver

efektivní způsob implementace stránkování

Pokusíme se vám dát stručnou odpověď na vaše pochybnosti, pokud spustíte skip(n).take(m) metody na linq (s SQL 2005 / 2008 jako databázovým serverem) bude váš dotaz používat Select ROW_NUMBER() Over ... s je nějakým způsobem přímé stránkování v enginu SQL.

Dám vám příklad, mám db tabulku s názvem mtcity a napsal jsem následující dotaz (pracujte také s 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.
}

Výsledný dotaz bude:

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]

Což je přístup k datům v okně (docela cool, mimochodem protože bude vracet data od samého začátku a bude mít přístup k tabulce, pokud budou splněny podmínky). Bude to velmi podobné:

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

S výjimkou toho, že tento druhý dotaz bude proveden rychleji než výsledek linq, protože k vytvoření okna pro přístup k datům bude používat výhradně index; to znamená, že pokud potřebujete nějaké filtrování, filtrování by mělo být (nebo musí být) ve výpisu Entity (kde je vytvořen řádek) a také by měly být vytvořeny některé indexy, aby byl zachován dobrý výkon.

Co je teď lepší?

Pokud máte ve své logice do značné míry solidní pracovní postup, implementace správného způsobu SQL bude komplikovaná. V tom případě bude řešením LINQ.

Pokud můžete tuto část logiky snížit přímo na SQL (v uložené proceduře), bude to ještě lepší, protože můžete implementovat druhý dotaz, který jsem vám ukázal (pomocí indexů), a umožnit SQL generovat a ukládat prováděcí plán dotaz (zlepšení výkonu).



  1. SQLite JSON_TYPE()

  2. SQLite MIN

  3. Průvodce pro CTE v SQL Server

  4. efektivní způsob, jak otestovat, zda existuje řádek tabulky