在SQL Server上填充tempdb的dense_rank?

Ser*_*sen 2 sql sql-server sql-server-2008

我在这里有这个查询,它使用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
Run Code Online (Sandbox Code Playgroud)

Rem*_*anu 7

任何必须对大型数据集进行排序的操作都可能会填充tempdb.dense_rank也不例外,就像rank,row_number,ntile等一样.

从数据库启动开始,您要求对每个扫描条目的全局完整类型进行排序.您表达查询的方式是连接必须在排序之前发生,因此排序将既大又宽.在完成所有操作后,消耗了大量的IO,CPU和tempdb空间,您将结果限制为仅针对指定顺序和某些条件的小子集(其中提到了投影中不存在的列,因此它们必须是一些制作的例子不是真正的代码).

  • 你有一个过滤器WHERE gn=1后跟一个GROUP BY gn.这是不必要的,gn在谓词中已经是唯一的,因此它无法为该组贡献.
  • 您在每个订单扫描中计算dense_rank,然后进行过滤p.OrderNumber = @OrderNumber AND p.gn = 1.这更没意义.如果@OrderNumber恰好包含所有订单的排名为1的扫描,则此查询将仅返回结果!它不可能是正确的.

你的查询毫无意义.慢的事实只是一个奖励.发布您的实际要求.

如果要了解性能调查,请阅读如何分析SQL Server性能.

PS.通常,计算等级和选择= 1总是可以表示为TOP(1)相关子查询,通常具有更好的结果.索引显然有帮助.

PPS.使用group by而没有任何聚合函数是另一个严重的代码味道.