【发布时间】:2016-08-20 16:42:11
【问题描述】:
小测验,SQL Server 能手:
下面的student 子查询会被执行多少次? (假设something 至少有十行):
SELECT TOP 10 a, b
, (SELECT type_id
FROM type
WHERE type_code = 'student') student
FROM something
如果你说 1,那么和我一样,你假设 SQL Server 会将 student 的值识别为一个不变的标量。
不幸的是,答案是 10:
我知道,我会使用 CTE!
WITH codes (student) AS (
SELECT (SELECT type_id
FROM type
WHERE type_code = 'student')
)
SELECT TOP 10 a, b
, student
FROM something
CROSS JOIN codes
结果完全一样。
当然,我可以通过先将标量捕获到变量来获得所需的效率:
DECLARE @Student tinyint
SELECT @Student = type_id
FROM type
WHERE type_code = 'student'
SELECT TOP 10 a, b
, @Student student
FROM something
这只会进行一次搜索,并且不会向主查询计划添加任何内容:
但是除了更冗长之外,如果您要定义一个内联表值函数,这意味着您还必须写出一个隐含的返回模式,这很麻烦(并为错误添加了一个向量)。
有没有办法编写一个只运行一次子查询的单个查询?
【问题讨论】:
-
出于兴趣,是不是 TOP 10 导致了这种行为?如果是这样,如果将 TOP 10 放在子查询中,然后使用不同的选项“加入”/“附加”标量常数会发生什么?
-
@MatBailie,这是有趣的。
TOP 0只是为了“简化”示例,但它确实影响了结果。当我删除它时,我确实得到了一次搜索,但它还添加了一个“Table Spool”,每行执行一次,总成本为 90%。因此,很高兴知道这会产生意想不到的效果,但接受的答案中的建议最终仍然比原来的更简单、更有效——符合我最初的预期。当“MWE”不够“M”时,就会发生这种情况!
标签: sql-server sql-execution-plan