CASE语句与临时表

时间:2016-05-30 23:45:40

标签: sql-server tsql

我可以在将代码转换为文本的两种不同技术之间做出选择:

insert into #TMP_CONVERT(code, value)
 (1, 'Uno')
,(2, 'Dos')
,(3, 'Tres')
;

coalesce(tc.value, 'Unknown') as THE_VALUE
...
LEFT OUTER JOIN #TMP_CONVERT tc
  on tc.code = x.code

或者

case x.code
when 1 then 'Uno'
when 2 then 'Dos'
when 3 then 'Tres'
else 'Unknown'
end as THE_VALUE

该表有大约2000万行。 代码查找表的典型大小为10行。

我宁愿选择#1,但我不喜欢留下外连接。

我的问题是:

  1. 以任何真正有意义的方式比另一个更快吗?

  2. 是否有任何SQL引擎都优化了这一点?那就是:它只是将表读入内存本质上就是case语句逻辑了吗?

  3. 我碰巧使用tsql,但我想知道任何数量的RDBM系统,因为我使用了几个。

    [编辑澄清不喜欢LEFT OUTER JOIN] 我需要时使用LEFT OUTER JOINS,但每当我使用它们时,我会仔细检查我的逻辑和数据以确认我确实需要它们。然后我在代码中添加注释,指出我使用LEFT OUTER JOIN的原因。当我使用INNER JOIN时,我必须做类似的练习;那就是:确保我没有丢弃数据。

3 个答案:

答案 0 :(得分:0)

使用join会有一些开销。但是,如果将code设为主群集密钥,则两者的性能可能具有可比性 - join甚至可以获胜。如果没有索引,我希望case略好于left join

这些只是猜测。但是,与所有性能问题一样,您应该检查系统上的数据。

我也想对你不喜欢left join做出反应。这些为SQL提供了重要的功能,是解决此问题的正确方法。

答案 1 :(得分:0)

为连接执行的代码可能远远超过为硬编码的case选项执行的代码。

执行计划将有一个额外的连接迭代器以及一个额外的扫描或搜索操作符(取决于合适索引的可用性)。从积极的方面看,10行将全部放在#TMP_CONVERT的单个页面上,无论如何这都将在内存中,它也是一个临时表,它每次都会因为获取和释放行锁而烦恼,但仍然是锁定页面,找到正确的行,并从其中破解所需的列值超过20,000,000次迭代的代码可能会增加一些可测量的CPU时间,而不是查找硬编码的值列表(可能你可以尝试嵌套的CASE语句,以执行二进制搜索并避免在那里需要10个分支。)

但即使存在可测量的时间差异,作为整个查询时间的一部分,它仍然可能不是特别重要。测试一下。让我们知道你发现了什么...

答案 2 :(得分:0)

在这种情况下,您还可以使用with构造来避免创建临时表。所以你的查询可能是这样的。

WITH TMP_CONVERT(code,value) AS -- Semicolon can be required before WITH.
(
    SELECT * FROM (VALUES (1,'UNO'), 
                          (2,'DOS'),
                          (3,'Tres')
    ) tbl(code,value)
)
coalesce(tc.value, 'Unknown') as THE_VALUE
...
LEFT OUTER JOIN TMP_CONVERT tc
  on tc.code = x.code

甚至可以使用子查询:

coalesce(tc.value, 'Unknown') as THE_VALUE
...
LEFT OUTER JOIN (VALUES (1,'UNO'), 
                        (2,'DOS'),
                        (3,'Tres')
        ) tc(code,value) 
        ON tc.code = x.code

希望这会有所帮助。