Sql 与所有其他查询相比,如果查询不经常运行,那么最好只进行查询优化:创建额外列/视图的努力可能没有回报。

Sql 与所有其他查询相比,如果查询不经常运行,那么最好只进行查询优化:创建额外列/视图的努力可能没有回报。,sql,performance,sql-server-2008,pagination,Sql,Performance,Sql Server 2008,Pagination,令人难以置信的是,没有其他答案提到在所有SQL Server版本中进行分页的最快方法,特别是关于OP的问题,对于大页码,偏移量可能非常慢 在SQL中执行分页有一种完全不同、速度更快的方法。如中所述,这通常称为“查找方法” @previousOrderDate和@previousOrderId值是上一页最后一条记录的相应值。这允许您获取“下一页”。如果按排序的方向是DESC,只需使用谢谢@a1ex07。有没有其他更好的方法可以在sql server 2008中编写分页查询?谢谢@Anup Shah

令人难以置信的是,没有其他答案提到在所有SQL Server版本中进行分页的最快方法,特别是关于OP的问题,对于大页码,偏移量可能非常慢

在SQL中执行分页有一种完全不同、速度更快的方法。如中所述,这通常称为“查找方法”


@previousOrderDate
@previousOrderId
值是上一页最后一条记录的相应值。这允许您获取“下一页”。如果按排序的
方向是
DESC
,只需使用
谢谢@a1ex07。有没有其他更好的方法可以在sql server 2008中编写分页查询?谢谢@Anup Shah提供详细的答案。我将检查这个+1嘿,我测试了这个解决方案,并根据我下面的建议将它与相应的查询进行了比较。在有100k条记录的样本表上,它显示您的查询占用了59%的总时间,而我的查询只占用了41%。当我将测试样本增加到1.6M时,对于记录50000-50010,它提高到69%和31%,但当我将范围移动到250000-25010时,优势降低到60%,而不是40%。最后,对于记录750000到750010(相当于堆的中间),差值为56% vs 44%。进一步的测试可能会很有趣,但除此之外,我的解决方案要简单得多。@Peru:这里有一个很好的基准来确认您的不良偏移性能:。我想你们可能会感兴趣,它允许在固定时间内分页如何运行完整的查询,并提供
CREATE TABLE
,包括相关表的索引。@Peru,orders表的结构是什么?
SELECT  *
FROM    ( SELECT    ROW_NUMBER() OVER ( ORDER BY OrderDate ) AS RowNum, *
          FROM      Orders
          WHERE     OrderDate >= '1980-01-01'
        ) AS RowConstrainedResult
WHERE   RowNum >= 1
    AND RowNum < 20
ORDER BY RowNum
WHERE   RowNum >= 1
    AND RowNum < 20  ==>executes faster approx 2 sec


    WHERE   RowNum >= 1000
    AND RowNum < 1010      ==>  more time  approx 10 sec

    WHERE   RowNum >= 30000
    AND RowNum < 30010    ==> more time approx 17 sec
    SELECT q2.*
    FROM
    (
        SELECT ROW_NUMBER() OVER ( ORDER BY OrderDate ) AS RowNum, OrderDate
        FROM      Orders
        WHERE     OrderDate >= '1980-01-01'
    )q1
    INNER JOIN 
    (
        SELECT ROW_NUMBER() OVER ( ORDER BY OrderDate ) AS RowNum, *
        FROM      Orders
        WHERE     OrderDate >= '1980-01-01'
    )q2
        ON q1.RowNum=q2.RowNum AND q1.OrderDate=q2.OrderDate AND q1.rownum BETWEEN 30000 AND 30020
    IF object_id('TestSelect','u') IS NOT NULL
        DROP TABLE TestSelect
    GO
    CREATE TABLE TestSelect
    (
        OrderDate   DATETIME2(2)
    )
    GO

    DECLARE @i bigint=1, @dt DATETIME2(2)='01/01/1700'
    WHILE @I<=2000000
    BEGIN

        IF @i%15 = 0
            SELECT @DT = DATEADD(DAY,1,@dt)

        INSERT INTO dbo.TestSelect( OrderDate )
        SELECT @dt

        SELECT @i=@i+1
    END
    SELECT q2.*
    FROM
    (
        SELECT  ROW_NUMBER() OVER ( ORDER BY OrderDate ) AS RowNum 
                ,OrderDate
        FROM TestSelect
        WHERE OrderDate >= '1700-01-01'
    )q1
    INNER JOIN
    (
        SELECT  ROW_NUMBER() OVER ( ORDER BY OrderDate ) AS RowNum 
                ,*
        FROM TestSelect
        WHERE OrderDate >= '1700-01-01'
    )q2
        ON q1.RowNum=q2.RowNum 
        AND q1.OrderDate=q2.OrderDate 
        AND q1.RowNum BETWEEN 50000 AND 50010
declare @pageOffset int
declare @pageSize int
-- set variables at some point

declare @startRow int
set @startRow = @pageOffset * @pageSize

declare @endRow int
set @endRow + @pageSize - 1

SELECT 
    o.*
FROM
(
    SELECT 
        ROW_NUMBER() OVER ( ORDER BY OrderDate ) AS RowNum
        , OrderId
    FROM      
        Orders
    WHERE     
        OrderDate >= '1980-01-01'
) q1
INNER JOIN Orders o
    on q1.OrderId = o.OrderId
where
    q1.RowNum between @startRow and @endRow
order by
    o.OrderDate
select RowNum, order_id from   
( select 
ROW_NUMBER() OVER ( ORDER BY OrderDate ) AS RowNum, 
o.order_id 
from orders o where  o.order_id > 0 ;  
) 
tmp_qry where RowNum between 1 and 10 order by RowNum; // first 10 
select RowNum, order_id from   
( select 
ROW_NUMBER() OVER ( ORDER BY OrderDate ) AS RowNum, 
o.order_id 
from orders o where  o.order_id > 17 ;  
) 
tmp_qry where RowNum between 1 and 10 order by RowNum; // next 10 
SELECT TOP(11) *
FROM (
    SELECT TOP(1210) *
    FROM [...]
    ORDER BY something ASC
) subQuery
ORDER BY something DESC.
SELECT TOP 10 *
FROM Orders
WHERE OrderDate >= '1980-01-01'
AND ((OrderDate > @previousOrderDate)
  OR (OrderDate = @previousOrderDate AND OrderId > @previousOrderId))
ORDER BY OrderDate ASC, OrderId ASC