Sql Server - 外部应用与子查询
请考虑 Sql Server 中的以下 2 条语句:
这一条使用嵌套子查询:
WITH cte AS
(
SELECT TOP 100 PERCENT *
FROM Segments
ORDER BY InvoiceDetailID, SegmentID
)
SELECT *, ReturnDate =
(SELECT TOP 1 cte.DepartureInfo
FROM cte
WHERE seg.InvoiceDetailID = cte.InvoiceDetailID
AND cte.SegmentID > seg.SegmentID),
DepartureCityCode =
(SELECT TOP 1 cte.DepartureCityCode
FROM cte
WHERE seg.InvoiceDetailID = cte.InvoiceDetailID
AND cte.SegmentID > seg.SegmentID)
FROM Segments seg
这使用 OUTER APPLY 运算符:
WITH cte AS
(
SELECT TOP 100 PERCENT *
FROM Segments
ORDER BY InvoiceDetailID, SegmentID
)
SELECT seg.*, t.DepartureInfo AS ReturnDate, t.DepartureCityCode
FROM Segments seg OUTER APPLY (
SELECT TOP 1 cte.DepartureInfo, cte.DepartureCityCode
FROM cte
WHERE seg.InvoiceDetailID = cte.InvoiceDetailID
AND cte.SegmentID > seg.SegmentID
) t
考虑到两个 Segments 表可能有数百万行,这 2 条语句中哪一条可能会执行得更好?
我的直觉是 OUTER APPLY 会表现得更好。
还有几个问题:
- 几乎我对此非常确定,但仍然想确认在第一个解决方案中,CTE 将有效地执行两次(因为它被引用两次并且 CTE 像宏一样内联扩展)。
- 在 OUTER APPLY 运算符中使用时,CTE 会为每行执行一次吗?当在第一个语句的嵌套查询中使用时,它还会对每一行执行吗?
Please consider the following 2 statements in Sql Server:
This one is using Nested sub-queries:
WITH cte AS
(
SELECT TOP 100 PERCENT *
FROM Segments
ORDER BY InvoiceDetailID, SegmentID
)
SELECT *, ReturnDate =
(SELECT TOP 1 cte.DepartureInfo
FROM cte
WHERE seg.InvoiceDetailID = cte.InvoiceDetailID
AND cte.SegmentID > seg.SegmentID),
DepartureCityCode =
(SELECT TOP 1 cte.DepartureCityCode
FROM cte
WHERE seg.InvoiceDetailID = cte.InvoiceDetailID
AND cte.SegmentID > seg.SegmentID)
FROM Segments seg
And this uses an OUTER APPLY operator:
WITH cte AS
(
SELECT TOP 100 PERCENT *
FROM Segments
ORDER BY InvoiceDetailID, SegmentID
)
SELECT seg.*, t.DepartureInfo AS ReturnDate, t.DepartureCityCode
FROM Segments seg OUTER APPLY (
SELECT TOP 1 cte.DepartureInfo, cte.DepartureCityCode
FROM cte
WHERE seg.InvoiceDetailID = cte.InvoiceDetailID
AND cte.SegmentID > seg.SegmentID
) t
Which of these 2 would potentially perform better considering that both Segments table can potentially have millions of rows?
My intuition is OUTER APPLY would perform better.
A couple of more questions:
- Almost I am quite sure about this, but still wanted to confirm that in the first solution, the CTE would effectively be executed twice (because its referenced twice and CTE is expanded inline like a Macro).
- Would CTE be executed once for each row when used in the OUTER APPLY operator? Also would it be executed for each row when used in nested query in first statement??
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先,去掉 CTE 中的
前 100%
。此处未使用 TOP,如果您希望对结果进行排序,则应在整个语句的末尾添加 Order By。其次,为了解决您关于性能的问题,如果被迫进行猜测,我的赌注将是第二种形式,因为它有一个子查询而不是两个。第三,您可以尝试的另一种形式是:另一种可能性
First, get rid of the
Top 100 Percent
in the CTE. You are not using TOP here and if you wanted the results sorted, you should add an Order By to the end of the entire statement. Second, to address your question about performance, and if forced to make a guess, my bet would be on the second form only because it has a single subquery instead of two. Third, another form which you might try would be:Another possibility
也许我会使用托马斯查询的这种变体:
Maybe I will use this variation of Thomas' query: