【问题标题】:Can "constant" lookups be done efficiently within a single query?可以在单个查询中有效地完成“恒定”查找吗?
【发布时间】: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


【解决方案1】:

对于这个查询:

SELECT TOP 10 a, b,
      (SELECT type_id FROM type WHERE type_code = 'student'
      ) as student
FROM something;

您希望在type(type_code, type_id) 上建立索引。

如果您将子查询移至FROM 子句,您可能会发现这样更有效:

SELECT TOP 10 a, b,
       t.type_id
FROM something s CROSS JOIN
     (SELECT type_id FROM type WHERE type_code = 'student'
     ) t

甚至:

SELECT TOP 10 s.a, s.b, t.type_id
FROM something s JOIN
     type t
     ON t.type_code = 'student';

【讨论】:

  • 问题不在于没有使用索引(确实如此)——而是在每一行都使用它来查找相同的值。我对type_code 有一个UNIQUE 约束,它隐式创建了一个索引,计划表明正在使用该索引。不过,我尝试了您的建议,得到了相同的结果。
  • @harpo 。 . .对。正确的解决方法是将子查询移到FROM
  • 谢谢,戈登!这两者都会导致对类型表的一次查找。我特别希望CROSS JOIN 在语义上与我的 CTE 版本没有区别。我在那里将标量作为子选择进行,因为实际上有不止一个代码查找。无论如何,再次感谢您的建议!
猜你喜欢
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 2013-04-13
  • 2012-02-06
  • 2015-03-26
  • 1970-01-01
  • 1970-01-01
  • 2011-09-05
相关资源
最近更新 更多