如何有效地从视图中的另一个表中查找常量值(只需一次)?

时间:2015-04-01 19:50:57

标签: sql sql-server tsql

我有一个视图,需要查找配置值并将其作为视图结果的每一行中的一列返回。这个值在SELECT的持续时间内基本上是一个常量(实际上,通常在几个月内保持不变,并且对于每个客户来说肯定是不同的)。这是一个人为的例子:

CREATE VIEW Baz
AS
   SELECT foo,
          (SELECT [Value] FROM [Config] WHERE [Key] = N'MyKey') AS ConstantValue,
          bar
     FROM myTable

问题在于,SQL计划显示正在为表中的每一行查找该值。这是一种浪费,绝对是计划中的“热点”。我希望它只是在ONCE中查找值,然后在每一行中使用它。

现在,在这个人为的例子中,计划没有显示它,但是在我制定的每个计划中,无论我如何尝试获得该常数值(使用WITH CTE,CROSS将该值应用于结果SELECT等等)计划总是显示值的索引搜索每行发生一次,而不是一次。

我无法对该值进行硬编码,因为它是一个随时间变化的配置值,并且对于每个客户数据库来说都是唯一不同的。

我正在显示多达40%的查询时间(在估计和实际计划中)仅用于这一次查找。做它ONCE将是一个重要的优化。有什么想法吗?

请参阅下面的计划部分:

Note the index Seek on SystemConfig

2 个答案:

答案 0 :(得分:1)

将表达式移动到from子句。它只会被评估一次:

CREATE VIEW Baz AS
   SELECT t.foo, k.ConstantValue, t.bar
   FROM myTable t CROSS JOIN
        (SELECT [Value] as ConstantValue FROM [Config] WHERE [Key] = N'MyKey') k;

答案 1 :(得分:0)

CREATE VIEW Baz
AS
   SELECT t.foo,
          c.Value AS ConstantValue,
          t.bar
      FROM myTable t
      join (SELECT [Value] FROM [Config] WHERE [Key] = N'MyKey') c on
         1 = 1

这只执行一次子查询,并将结果连接到MyTable的每一行。