Sql server CASE语句与临时表

Sql server CASE语句与临时表,sql-server,tsql,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 或 这个表大约有2000万行。 代码查找表的典型大小为10行 我倒愿意,但我不喜欢左外连接

在将代码转换为文本时,我可以选择两种不同的技术:

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

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

我倒愿意,但我不喜欢左外连接

我的问题是:

  • 一个比另一个快真的有意义吗

  • 是否有任何SQL引擎对此进行了优化?也就是说:它只是将表读入内存,实际上case语句的逻辑是什么

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

    [编辑以澄清不喜欢左外连接]
    当我需要左外部联接时,我使用左外部联接,但每当我使用它们时,我都会仔细检查我的逻辑和数据,以确认我确实需要它们。然后,我在代码中添加一条注释,指出我为什么使用左外连接。当然,当我使用内部连接时,我必须做类似的练习;也就是说:确保我没有删除数据。

    使用
    连接会有一些开销。但是,如果将
    code
    设为主集群键,那么这两个键的性能可能是相当的,
    join
    甚至胜出。如果没有索引,我希望
    案例
    略好于
    左连接

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


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

    使用
    连接会有一些开销。但是,如果将
    code
    设为主集群键,那么这两个键的性能可能是相当的,
    join
    甚至胜出。如果没有索引,我希望
    案例
    略好于
    左连接

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


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

    为联接执行的代码可能比为硬编码的
    case
    选项执行的代码多得多

    执行计划将有一个额外的连接迭代器和一个额外的扫描或搜索操作符(取决于合适索引的可用性)。从积极的一面来看,10行很可能都可以放在
    #TMP#u CONVERT
    中的一个页面上,并且这将在内存中,同时也是一个临时表,它不需要每次都获取和释放行锁,但仍然需要锁定页面的代码,找到正确的行,与在硬编码的值列表中查找相比,在20000000次迭代中从中取出所需的列值可能会增加一些可测量的CPU时间(可能您也可以尝试嵌套的
    CASE
    语句,以执行二进制搜索,并避免在那里需要10个分支)


    但即使存在可测量的时间差,它在整个查询时间中所占的比例也可能不是特别显著。测试一下。让我们知道您发现了什么…

    为联接执行的代码可能远远超过为硬编码的
    案例执行的代码

    执行计划将有一个额外的连接迭代器和一个额外的扫描或搜索操作符(取决于合适索引的可用性)。从积极的一面来看,10行很可能都可以放在
    #TMP#u CONVERT
    中的一个页面上,并且这将在内存中,同时也是一个临时表,它不需要每次都获取和释放行锁,但仍然需要锁定页面的代码,找到正确的行,与在硬编码的值列表中查找相比,在20000000次迭代中从中取出所需的列值可能会增加一些可测量的CPU时间(可能您也可以尝试嵌套的
    CASE
    语句,以执行二进制搜索,并避免在那里需要10个分支)


    但即使存在可测量的时间差,它在整个查询时间中所占的比例也可能不是特别显著。测试一下。让我们知道您发现了什么…

    在这种情况下,您还可以通过使用
    构造来避免创建临时表。所以你可以这样问

    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
    

    希望这能有所帮助。

    在这种情况下,您也可以通过使用
    构造来避免创建临时表。所以你可以这样问

    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
    

    希望这能有所帮助。

    我想知道一个更倾向于在代码中查找数据而不是静态表的用例。在我遇到的任何情况下,我都会创建一个表,用户可以在不更改代码的情况下对其进行编辑。可能值得阅读Eric Lippert的优秀作品:"... 如果你有两匹马,你想知道这两匹马中哪一匹跑得更快,那就去比赛吧。不要写马的简短描述,把它们发布在互联网上,让随机的陌生人猜哪个更快!“当你在2000万行上运行它们时,你会得到什么结果?我很好奇有一个用例更倾向于在代码中查找数据,而不是静态表。我遇到的任何情况下,我都会创建一个用户可以编辑的表,而无需更改代码。可能值得一读Eric Lippert的优秀作品:。。。如果你有两匹马,你想知道这两匹马中哪一匹跑得更快,那就去比赛吧。不要写马的简短描述,把它们发布在互联网上,让随机的陌生人猜哪个更快!“当您对2000万行运行它们时,会得到什么结果?