【问题标题】:Limit the number of rows being processed in this query限制此查询中正在处理的行数
【发布时间】:2011-12-10 18:59:38
【问题描述】:

我不能在这里发布实际的查询,所以我发布查询的基本大纲就足够了。该查询用于分页并返回一组根据函数的输出排序的用户,例如 F。F 从用户表和其他连接的表中获取参数。查询如下所示

Select TOP (20) 
from (select row_number OVER (Order By F desc) as rownum, 
             user.*, .. 
      from user 
      inner join X on user.blah = X.blah 
      left outer join Y on user.foo = Y.foo 
      where DATEDIFF(dd, LastLogin, GetDate()) > 200 and Y.bar > FUBAR) as temp 
where rownum > 0  

根据执行计划,91% 的成本在排序中。由于排序基于 F,我无法添加索引来加速排序。内部查询查询所有记录,过滤然后排序。现在大多数时候用户只查看 1 - 5 页中的结果(1 页有 20 条记录,因此是 Top(20))所以我在想是否有任何方法可以限制正在处理和排序的行并制作大多数时候,查询速度更快,CPU 密集度更低。

编辑:当我说计算 F 表已连接时,我的意思是这个。 F 接受 X.blah 和 Y.foo 和 Y.bar 等参数。就是这样。所有这些参数也需要作为结果集的一部分返回。例如用户最后位置的经纬度存储在X中。

【问题讨论】:

  • 谢谢!我进行了编辑以澄清我的意思。

标签: sql sql-server sql-server-2005 tsql


【解决方案1】:

至少你可以尽量不要在每一行都调用 DATEDIFF

declare @target_date datetime
set @target_date = DATEADD(dd, -200, GetDate())

Select TOP (20) 
from (select row_number OVER (Order By F desc) as rownum, 
             user.*, .. 
      from user 
      inner join X on user.blah = X.blah 
      left outer join Y on user.foo = Y.foo 
      where LastLogin < @target_date and Y.bar > FUBAR) as temp 
where rownum > 0  

也许对 FUBAR 和 F 做同样的事情?

上面的例子并没有给你太多的性能,但提供了一个关于如何减少函数调用的总体思路

【讨论】:

    【解决方案2】:

    不确定它是否有帮助以及有多大帮助 - 但有两件事:

    1. 您能否确保WHERE 子句(user.blahX.blahuser.fooY.fooY.bar)中的所有外键列和列确实都已编入索引?这将显着提高 JOIN 性能。

      如果这些列未编入索引,则 SQL Server 使用的执行计划中也可能存在排序操作,因此它可以对数据使用合并联接。所以你的排序甚至可能不是真正来自你认为导致排序的OVER (ORDER BY F DESC)

    2. 您将TOP (20) 与行号组合在一起,但您没有为完整的结果集定义任何真正的ORDER BY - 所以您的结果充其量是随机的。另外,如果你已经定义了rownum,你就不能使用:

      SELECT (columns)
      FROM (.......) as temp 
      WHERE rownum BETWEEN 0 AND 20 
      

    【讨论】:

      【解决方案3】:

      一些想法:

      1. F是什么函数?它可以重写为内联表值函数吗?这将使优化器有机会将函数扩展为可重用的执行计划。

      2. 您正在对 Y 执行 LEFT OUTER JOIN,但随后在 WHERE 子句中包含来自 Y 的列,从而有效地将其呈现为 INNER JOIN。尽管优化器可能以相同的方式呈现执行计划,但我会清理它以便将来更容易排除故障。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-15
        • 2019-11-30
        • 2019-06-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多