加入收藏 | 设为首页 | 会员中心 | 我要投稿 核心网 (https://www.hxwgxz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程 > 正文

sql-server – 通过数百万行的可自定义排序进行分页性能

发布时间:2020-12-26 03:08:55 所属栏目:编程 来源:网络整理
导读:在我们的应用程序中,我们有一个网格,用户可以在其中分页大量记录(1000万到2000万).网格支持在多个列(20)中按升序和降序排序.许多值也不是唯一的,因此应用程序也会将id排序为打破平局,以确保行始终显示在同一页面上.例如,如果用户想要按窗口小部件大小排序(从

对于30行的第一页,实现如下所示:

DECLARE 
    @TopRows bigint = 30,@Minimum integer;

SELECT TOP (1)
    @Minimum = Filtered.widgetSize
FROM 
(
    SELECT * FROM 
    (
        SELECT
            WS.widgetSize,WS.NumRows,-- SQL Server 2012 or later
            SumNumRows = SUM(WS.NumRows) OVER (
                ORDER BY WS.widgetSize DESC)
        FROM dbo.WidgetSizes AS WS WITH (NOEXPAND)
    ) AS RunningTotal
    WHERE 
        RunningTotal.SumNumRows >= @TopRows
) AS Filtered
ORDER BY 
    Filtered.SumNumRows ASC;

SELECT TOP (@TopRows)
    T.id,T.widgetSize
FROM dbo.Test AS T
WHERE T.widgetSize >= @Minimum
ORDER BY
    T.widgetSize DESC,T.id ASC;

执行计划:

这显着改善了执行时间,大部分剩余成本与表扫描和下推过滤器相关联.通过创建非聚簇列存储索引(SQL Server 2012以后)可以进一步提高性能:

CREATE NONCLUSTERED COLUMNSTORE INDEX 
    NCCI_Test_id_widgetSize 
ON dbo.Test (id,widgetSize);

在我的笔记本电脑上,在列存储索引上以批处理模式执行扫描和过滤将执行时间从大约300毫秒减少到仅20毫秒:

下一页

第一页查询返回的最后一行包含widgetSize = 2903和id = 327:

查找接下来的30行(第2页)只需要对上一个查询进行简单修改:

DECLARE 
    @TopRows bigint = 30,SumNumRows = SUM(WS.NumRows) OVER (
                ORDER BY WS.widgetSize DESC)
        FROM dbo.WidgetSizes AS WS WITH (NOEXPAND)
        WHERE
            -- Added
            WS.widgetSize < 2903
    ) AS RunningTotal
    WHERE 
        RunningTotal.SumNumRows >= @TopRows
) AS Filtered
ORDER BY 
    Filtered.SumNumRows ASC;

SELECT TOP (@TopRows)
    T.id,T.widgetSize
FROM dbo.Test AS T
WHERE 
    T.widgetSize >= @Minimum
    AND 
    (
        -- Added
        T.widgetSize < 2903
        OR (widgetSize = 2903 AND id > 327)
    )
ORDER BY
    T.widgetSize DESC,T.id ASC;

这会产生与原始查询的明显扩展相同的结果:

SELECT TOP 30
    * -- (Pretend that there is a list of columns here)
FROM Test
    WHERE widgetSize < 2903
    OR (widgetSize = 2903 AND id > 327)
ORDER BY
    widgetSize DESC,id ASC;

使用索引视图和非聚簇列存储索引的查询在25ms内完成,而原始版本则超过2000ms.

传统的索引方案

或者,如果您要创建(最小的,非覆盖的)非聚簇索引以支持最常见的排序请求,那么查询优化器将使用它们来满足TOP(30)查询的可能性非常大.索引压缩可用于最小化这些附加索引的大小.

(编辑:核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读