【问题标题】:SQL Server stored procedure running very slowSQL Server 存储过程运行很慢
【发布时间】:2018-09-01 13:45:20
【问题描述】:

我的场景:我有一个包含 10M+ 行和 10 列的表(表名:Giggerdata)。我的存储过程设计为当我传递两个参数(pageNumber, pageSize)时,它将Giggerdata 表记录分成页面(每个页面有 10M/pageSize 记录)。它只会返回传入的pageNumber 上的那些记录。

我从外部服务调用存储过程,该服务以 30 MB 的批量迭代我的表(这是我正在使用的 API 的限制)。我会逐页有效地遍历这个表(每页有 30MB 的记录)并通过另一个 API 推送该数据。

我需要加快这个存储过程的速度,因为使用pageNumber = 1pageSize = 400,000 需要>3 分钟才能获得结果,而通过这种迭代方式导出我的整个表格需要>1 小时(我的应用程序无法接受)。

我已经阅读了存储过程问题,并尝试更改我的存储过程以考虑参数嗅探;有人可以查看我的存储过程并确定我是否正确实施了本地参数解决方案吗?

我可以采取其他措施来加快速度吗?

我的存储过程:

ALTER PROCEDURE [dbo].[mySP]
    @pageNumber INT, 
    @pageSize INT
AS 
BEGIN
    DECLARE @locpageNumber INT, @locpageSize INT

    SELECT @locpageNumber = @pageNumber, @locpageSize = @pageSize 

    SELECT *
    FROM dbo.GiggerData
    ORDER BY Col1
        OFFSET @locpageSize * (@locpageNumber - 1) ROWS
        FETCH NEXT @locpageSize ROWS ONLY
    OPTION (RECOMPILE)
END

测试代码:

DECLARE @return_value INT
EXEC    @return_value = dbo.[mySP]
            @pageNumber = 41,
            @pageSize = 500000

SELECT  'Return Value' = @return_value
GO

【问题讨论】:

  • 查询计划是什么样的? Col1 上是否有聚集索引?
  • 从数据库中一次性查询所有内容(就像您将所有集合合并在一起一样)。然后将其从内存中流式传输到您的 api。
  • 如果你必须迭代地做,如果你的大部分调用都是一样的,你可能不想每次都重新编译那个语句。也许只有当你向它传递某个参数或其他东西时。可能不会在 3 分钟和 60 分钟之间产生差异,但它可能会有所帮助
  • 没有索引(Col1 有重复和空白)。该解决方案适用于不同的应用程序(不确定导出后如何查询)。
  • 另外:您是否尝试过调整页面大小以查看是否可以在那里进行任何优化?这实际上可能是使用客户端库而不是 SP 更快的情况,即:docs.microsoft.com/en-us/dotnet/framework/data/adonet/…

标签: sql-server stored-procedures optimization


【解决方案1】:

使用OFFSETFETCH 的分页将随着每一页而逐渐变慢,因为SQL Server 仍需要在有序行集的开头启动。如果GiggerData_Key是唯一聚集索引,可以使用更高效的基于键的分页方式:

SELECT TOP (500000) *
FROM dbo.GiggerData
WHERE GiggerData_Key > @Last_GiggerData_Key_Returned
    OR @Last_GiggerData_Key_Returned IS NULL --first page
ORDER BY GiggerData_Key`;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-27
    • 1970-01-01
    • 1970-01-01
    • 2014-05-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多