我在这里有这个查询,它使用dense_rank来编号组,以便只选择第一组。它正在工作,但它的慢速和tempdb(SQL服务器)变得如此之大,以至于磁盘已满。对于dense_rank这么重的操作来说,这是正常的吗?那么如何在不诉诸编码的情况下完成这项工作呢?
select
a,b,c,d
from
(select a,b,c,d,
dense_rank() over (order by s.[time] desc) as gn
from [Order] o
JOIN Scan s ON s.OrderId = o.OrderId
JOIN PriceDetail p ON p.ScanId = s.ScanId) as p
where p.OrderNumber = @OrderNumber
and p.Number = @Number
and p.Time > getdate() - 20
and p.gn = 1
group by a,b,c,d,p.gn
答案 0 :(得分:7)
任何必须对大型数据集进行排序的操作都可能会填充tempdb。 dense_rank也不例外,就像rank,row_number,ntile等等。
自从数据库启动以来,您要求对每个扫描条目的全局完整类型进行排序。您表达查询的方式是连接必须在排序之前发生,因此排序将既大又宽。在完成所有操作后,消耗了大量的IO,CPU和tempdb空间,您将结果限制为仅针对指定顺序和某些条件的小子集(其中提到了投影中不存在的列,因此它们必须是一些制作的例子不是真正的代码。)
WHERE gn=1
上有一个过滤器,后跟GROUP BY gn
。这是不必要的,gn在谓词中已经是唯一的,所以它无法为该组贡献。p.OrderNumber = @OrderNumber AND p.gn = 1
进行过滤。这更没意义。如果@OrderNumber恰好包含所有订单的排名为1的扫描,则此查询将仅返回结果!它可能不正确。您的查询毫无意义。慢的事实只是一个奖励。发布您的实际要求。
如果您想了解效果调查,请阅读How to analyse SQL Server performance。
PS。通常,计算等级和选择= 1总是可以表示为TOP(1)相关子查询,通常具有更好的结果。索引显然有帮助。
PPS。使用group by而不使用任何聚合函数是另一个严重的代码味道。