【问题标题】:SQL: left join vs CASE subquery - which is more efficientSQL:左连接 vs CASE 子查询——效率更高
【发布时间】:2019-05-06 12:29:38
【问题描述】:

你们认为哪一个更高效(负载更少)?

SELECT t1.a, 
(CASE
WHEN t1.p=1 THEN t2.g 
WHEN t1.p=2 THEN t3.g
END) as v

FROM t1
LEFT JOIN t2 ON t1.x=t2.x
LEFT JOIN t3 ON t1.y=t3.y

SELECT 
t1.a, t2.v 

FROM t1    
outer apply (
SELECT v= CASE
WHEN t1.p=1 THEN (SELECT v FROM t2 WHERE t1.x=t2.x)
WHEN t1.p=2 THEN (SELECT v FROM t3 WHERE t1.y=t3.y)
END
) t2

只是想弄清楚sql引擎是如何工作的..

[我想在这个问题中研究什么] 在第一个查询中,表t2t3 将始终被调用,但在第二个查询中,它们仅在大小写匹配时才会被调用(因此负载较少 = 仅检查 2 个表而不是每行 3 个)?

【问题讨论】:

  • 执行计划怎么说?设置比较结果的统计信息?

标签: sql tsql join left-join outer-apply


【解决方案1】:

我会选择left join,但写成:

SELECT t1.a, COALESCE(t2.g, t3.g) as v
FROM t1 LEFT JOIN
     t2
     ON t1.x = t2.x AND t1.p = 1 LEFT JOIN
     LEFT JOIN t3
     ON t1.y = t3.y AND t1.p = 2;

此逻辑不一定完全等同于您的逻辑,但我怀疑此查询符合您的意图。 (例如,如果t2.g 曾经是NULLt1.p = 1,那么结果就不一样了。)

就性能而言,LEFT JOIN 为优化器提供了比CASE 表达式更多的查询选项,因此它可能会更快。但是,通过适当的索引,所有三个查询都可能具有良好的性能。

【讨论】:

  • 好的,所以左连接将为优化器提供更好的选择,但 CASE 意味着要查看的表少了不是吗?
  • @RaheelHasan "CASE 意味着少了一张表,不是吗?" ,只有在t1.p 时才会这样始终为 1,或始终为 2
  • 在一行中,可以是 1,也可以是 2.. 不能同时是两个
【解决方案2】:

在每个左连接中放置一个额外的谓词t1.p=,以便它们根据结果的需要变得互斥。这将允许使用 coalesce 代替 case 表达式(但 case 表达式是可以的,它只是一个选项)。

在您的示例中没有令人信服的理由使用 apply 运算符,尽管它们确实比放置在 select 子句中的相关子查询优化得更好,但它们仍然是相关子查询。在我看来,如果“更具异国情调”的选项没有令人信服的理由,请不要使用它。所以,不要在这里使用 apply 运算符,使用更标准的左连接。

SELECT
    t1.a
  , COALESCE(t2.g,t3.g) AS v
FROM t1
LEFT JOIN t2 ON t1.x = t2.x AND t1.p = 1
LEFT JOIN t3 ON t1.y = t3.y AND t1.p = 2
;

但是,如果您只需要这些相关子查询中的一个(或规定数量)行那么您将有一个令人信服的理由使用应用程序,例如

SELECT
    t1.a
  , t2.v
FROM t1
OUTER APPLY (
        SELECT
            CASE
                WHEN t1.p = 1 THEN (
                        SELECT TOP(1) t2.g FROM t2  -- top 
                        WHERE t1.x = t2.x
                        ORDER BY t2.z               -- order
                    )
                WHEN t1.p = 2 THEN (
                        SELECT TOP(1) t3.g FROM t3  -- top
                        WHERE t1.y = t3.y
                        ORDER BY t3.z               -- order
                    )
            END AS v
    ) t2

不管意见如何,使用执行计划是比较查询选项的最佳方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-02
    • 1970-01-01
    • 2019-08-19
    • 1970-01-01
    相关资源
    最近更新 更多