【问题标题】:T-SQL UNION Performance issueT-SQL UNION 性能问题
【发布时间】:2015-12-11 06:27:00
【问题描述】:

我有两种查询在这里做了同样的工作

查询 1:

SELECT MP.MemberName FROM MemberProfile MP 
LEFT JOIN Order O ON MP.MemberID = O.MemberID
WHERE O.TotalAmount >= 100

UNION

SELECT MP.MemberName FROM MemberProfile MP
LEFT JOIN Order O ON MP.MemberID = O.MemberID
WHERE O.Quantity >= 10

查询 2:

;WITH cte AS (
     SELECT MP.MemberName, O.Quantity, O.TotalAmount FROM MemberProfile MP 
     LEFT JOIN Order O ON MP.MemberID = O.MemberID
)
SELECT MemberName FROM cte WHERE TotalAmount >= 100

UNION

SELECT MemberName FROM cte WHERE Quantity >= 10

在实际环境中查询会比较复杂,这些只是一个简单的版本供其他人阅读

问题:

  1. 基于性能和冗余,使用 CTE 而不是每次都使用 JOIN 更好吗?

  2. 除了这些方法之外,还有更好的方法来执行此 UNION 甚至 UNION ALL 查询吗?

【问题讨论】:

  • 检查您的查询计划。我的猜测是 CTE 将被折叠以提供相同的查询计划,但请务必检查它。
  • 查询计划结果为这两种查询提供了非常小的成本差异,即使时间消耗也几乎没有明显的差异。可能会留下它或将其切换到真实环境进行测试。如果遇到性能问题,请进一步调整。无论如何,谢谢..
  • CTE 的作用类似于宏。CTE 具有良好的可读性,但与临时表相比,它的性能并不好,如果可能的话最好使用临时表。如果您要连接多个表,每个表都有数百万行记录,CTE 的性能将明显低于临时表。
  • 不要只检查执行计划 - 使用 STATISTICS IO 和 STATISTICS 时间来查看确切的值,因为正如@DashangG.Makwana 所提到的 - 如果不小心处理大数据,CTE 的性能可能会非常糟糕/半大型结果集。
  • 使用 UNION ALL 代替 UNION 将提高性能,除非您需要消除结果中的重复行(如您的示例)。此外,您可以在示例查询中使用INNER JOIN,因为WHERE 子句谓词引用外部表并且永远不会返回NULL 值。

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


【解决方案1】:

在您的情况下,我认为 CTE 和 JOIN 之间不会有任何大的区别。 SQL Server 优化会将其转换为完全不同的东西,这两个查询可能会产生相同的结果。如果选择性很高,您可以尝试在 TotalAmount 和 Quantity 上添加索引。

【讨论】:

  • 关于使用索引的好处,我会尝试进一步调整......谢谢任何地方
猜你喜欢
  • 1970-01-01
  • 2021-10-25
  • 2011-05-21
  • 2017-12-10
  • 2022-01-15
  • 1970-01-01
  • 2017-12-10
  • 2016-11-04
相关资源
最近更新 更多