【问题标题】:Slow CTE Subquery in MSSQLMSSQL 中的慢速 CTE 子查询
【发布时间】:2017-08-23 11:17:12
【问题描述】:

我有一个查询,它占用我的 SQL 2008 DB 1.4 秒。然后我尝试使用这个模板做一个子查询:

;with __myResults as (
    ... my initial query ... already has a column:
    row_number() over (ORDER BY ...) as RowNum
)
select * from __myResults where RowNum between X and Y

如果我将 X 和 Y 设置为较低的数字,它会表现良好。大约需要 0.3 秒。 如果我将 X 和 Y 设置为较高的数字,它的性能甚至比初始查询还要差。如果我增加 X 和 Y,它会在运行时不断增加。

这怎么可能?

我试图做的是比较执行计划,但它们是相同的(只看“成本:n%”)

我该如何调试呢?我从哪里看出问题出在哪里?

我还尝试了以下方法:

where RowNum > highNumber

很快!而

where RowNum > highNumber and RowNum < highNumber + 10

很慢。最后:

where RowNum < highNumber

非常慢(6 秒)。

更新

我最终将结果放在了一个临时表中。然后进行过滤。这样好像很快。

【问题讨论】:

  • 只有当您在选择查询中引用 CTE 时才会调用它。在 where 子句中设置一个较低的 RowNum 会限制它,因此它只需要进行选择直到它匹配,增加它意味着它必须做更多的工作
  • 似乎使用 row_number 的方法用于将结果集切割成碎片?您是否考虑过使用offset fetch next?不过,它仅在 sql server 2012 之后才可用。
  • CTE 对结果集执行,因此集越大,查询越慢。 (因此 - 名称“窗口函数”)。有许多可能的解决方法,但它们取决于实际查询。但是,我要尝试的第一件事是将包含结果的行号选择到临时表(不是表变量)中,并将其用作基础而不是 CTE。如前所述 - 还有其他技术可以尝试,例如使用 select TOP 和 NOT IN,或使用联合和自连接来最小化查询并优化索引。但如果没有实际查询,很难给出建议

标签: sql sql-server performance common-table-expression database-performance


【解决方案1】:

为什么不使用FETCH/OFFSET

select *
from __myResults 
order by ??
offset X - 1
fetch next (X - Y) rows only;

您需要调整参数XY

【讨论】:

  • 感谢您的反馈。我刚刚意识到我们必须支持 MS SQL 2008 :(
  • 我只是测试了它。现在花费的最大时间,不比初始查询慢!谢谢。因此,即使使用了偏移量,也必须扫描整个查询,这可能是可以理解的。
  • @ims1234 。 . . order by 中的列是否有索引?
猜你喜欢
  • 1970-01-01
  • 2018-07-09
  • 2017-12-24
  • 1970-01-01
  • 2015-06-04
  • 2012-02-08
  • 2014-03-20
  • 1970-01-01
相关资源
最近更新 更多