【发布时间】:2018-09-01 13:45:20
【问题描述】:
我的场景:我有一个包含 10M+ 行和 10 列的表(表名:Giggerdata)。我的存储过程设计为当我传递两个参数(pageNumber, pageSize)时,它将Giggerdata 表记录分成页面(每个页面有 10M/pageSize 记录)。它只会返回传入的pageNumber 上的那些记录。
我从外部服务调用存储过程,该服务以 30 MB 的批量迭代我的表(这是我正在使用的 API 的限制)。我会逐页有效地遍历这个表(每页有 30MB 的记录)并通过另一个 API 推送该数据。
我需要加快这个存储过程的速度,因为使用pageNumber = 1 和pageSize = 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