实现分页的有效方法

 2023-02-17    412  

问题描述

我应该使用linq的Skip()和Take()方法来分页,或用sql查询实现自己的分页?

哪个最有效?为什么我会选择一个超过另一个?

实现分页的有效方法

我正在使用SQL Server 2008,ASP.NET MVC和LINQ.

推荐答案

试图为您的疑问提供简要答案,如果在Linq上执行skip(n).take(m)方法(使用SQL 2005/2008作为数据库服务器),您的查询将使用Select ROW_NUMBER() Over …语句,是以某种方式在SQL引擎中直接分页.

给你一个例子,我有一个名为mtcity的db表,我写了以下查询(以及Linq到实体的工作):

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

生成的查询将是:

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]

是一个窗口数据访问(相当酷,BTW CUZ将返回数据,因为只要满足条件,就可以访问该表.这将非常类似于:

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

除了情况下,该第二查询将从LINQ结果速度执行,因为它将仅使用索引来创建数据访问窗口;这意味着,如果您需要一些过滤,则过滤应在实体列表中(或在创建行的位置)中,并应创建某些索引,以保持良好的性能.

现在,什么更好?

如果您在逻辑中具有非常稳固的工作流程,则实现正确的SQL方式将复杂.在那种情况下,Linq将是解决方案.

如果您可以将该部分逻辑直接降低到SQL(在存储过程中),它会更好,因为您可以实现我向您展示的第二个查询(使用索引)并允许SQL生成并存储执行查询计划(提高性能).

其他推荐答案

尝试使用

FROM [TableX]
ORDER BY [FieldX]
OFFSET 500 ROWS
FETCH NEXT 100 ROWS ONLY

以在SQL Server中从501到600获取行,而不在内存中加载它们.请注意,此语法已可用 SQL Server 2012

其他推荐答案

而linq-to-sql,将生成OFFSET子句(可能使用ROW_NUMBER() OVER() 如其他人提到的),有一个完全不同的,更快的方法在SQL中进行分页.这通常被称为这个博客帖子在这里.

SELECT TOP 10 first_name, last_name, score
FROM players
WHERE (score < @previousScore)
   OR (score = @previousScore AND player_id < @previousPlayerId)
ORDER BY score DESC, player_id DESC

@previousScore和@previousPlayerId值是上一页的最后一条记录的相应值.这允许您获取”下一个”页面.如果ORDER BY方向是ASC,则只需使用>.

使用上述方法,您不能立即跳转到第4页而不首先提取前40个记录.但经常,无论如何,你不想跳跃.相反,您可以获得更快的查询,这可能能够在恒定时间内获取数据,具体取决于您的索引.加上,您的页面保持”稳定”,无论是底层数据更改(例如,第1页),在第4页的时候).

这是在Web应用程序中加载更多数据时实现分页的最佳方法.

注意,”seek方法”也称为 keyset paging

以上所述是小编给大家介绍的实现分页的有效方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对77isp云服务器技术网的支持!

原文链接:https://77isp.com/post/34239.html

=========================================

https://77isp.com/ 为 “云服务器技术网” 唯一官方服务平台,请勿相信其他任何渠道。