如何对记录进行分页,获取记录总数,同时保持性能?

问题描述 投票:0回答:2

我正在尝试提高复杂存储过程的性能。瓶颈是这个巨大的查询,它有超过 30 个连接(其中大部分都留下了),并且 WHERE 语句中的条件数量多得离谱。此外,SELECT 部分包含对多个函数的调用,这些函数也执行重要的工作。

伪示例:

select fn_DoWork1(caseID, orderID) as cln1,
       fn_DoWork2(caseID, orderID) as cln2,
       ... 20 other columns
       BalanceDue
from tbl1
   left join tbl2 on ...
   ...
   left join tbl30 on ...
where 
   (tbl10.ArrivalDate between @foo1 and @foo2)
   ...
   (@prmProcessingID = 0 OR tbl10.ProcessingID = @prmProcessingID)

你明白了。我将查询分成更小的部分,一路将数据存入临时表中,以便每个连续的查询都必须处理较小的子集。但最终,它仍然匹配了数千条记录,因此性能并没有像我希望的那样提高。

我的下一个想法是一次只返回 1 页记录(每页 20 条记录),因为这就是用户需要查看的全部内容。所以我添加了

OFFSET x ROWS
FETCH NEXT 20 ROWS ONLY
并解决了性能问题。

但是,现在的问题是我返回了 20 行,但我不知道总共有多少行符合条件。因此,我无法告诉用户有多少页数据 - 例如我无法在 UI 上正确呈现寻呼机。

有没有更好的方法来解决这个问题?

sql sql-server performance sql-server-2017
2个回答
1
投票

有没有更好的方法来解决这个问题?

计算行数需要评估整个数据集上的 JOIN 和 WHERE 子句,因此运行查询和存储结果的成本几乎很高。

您的选择是运行完整查询并缓存结果,或者采用不显示总页数的 UX。


-3
投票

尝试将查询分解为多个WITH语句,并将函数调用推迟到最后一个可能的查询,以简化查询结构。 从逻辑上讲,它们与一个大查询相同。

David Browne 是正确的,如果你不需要在前端 UI 中显示行数,就不要计算它。

我们按照这个顺序执行了所有的WITH语句

WITH customerData AS
(
   SELECT customer data fields used and join in lookup data WHERE filter in only active customers
),
purchaseOrders as
(
  SELECT purchase order fields where customer Id in CustomerData rows and date range in A to B
),
...

然后最终查询加入右侧的With语句并调用函数、case语句等

它的好处是你可以慢慢地将原始查询重构为一系列更简单的查询。

© www.soinside.com 2019 - 2024. All rights reserved.