【问题标题】:subselect vs outer join子选择与外连接
【发布时间】:2010-09-08 00:38:36
【问题描述】:

考虑以下 2 个查询:

select tblA.a,tblA.b,tblA.c,tblA.d
from tblA
where tblA.a not in (select tblB.a from tblB)

select tblA.a,tblA.b,tblA.c,tblA.d
from tblA left outer join tblB
on tblA.a = tblB.a where tblB.a is null

哪个性能更好?我的假设是,除了子选择返回非常小的结果集的情况外,连接通常会更好。

【问题讨论】:

    标签: sql sql-server database performance


    【解决方案1】:

    RDBMS 会“重写”查询以优化它们,因此这取决于您使用的系统,我猜它们最终会在大多数“好”数据库上提供相同的性能。

    为了我的钱,我建议选择更清晰、更易于维护的那个,那就是第一个。调试子查询要容易得多,因为它可以独立运行以检查其完整性。

    【讨论】:

      【解决方案2】:

      不相关的子查询很好。您应该使用描述您想要的数据的内容。如前所述,这可能会被重写到相同的计划中,但不能保证!更重要的是,如果表 A 和 B 不是 1:1,您将从连接查询中获得重复的元组(因为 IN 子句执行隐式 DISTINCT 排序),因此最好编写您想要的代码并实际考虑结果。

      【讨论】:

        【解决方案3】:

        嗯,这取决于数据集。根据我的经验,如果您的数据集较小,则选择 NOT IN,如果数据集较大,则选择 LEFT JOIN。 NOT IN 子句在大型数据集上似乎非常慢。

        我可能要补充的另一件事是解释计划可能具有误导性。我见过几个查询,其中的解释非常高,查询运行时间不到 1 秒。另一方面,我看到了具有出色解释计划的查询,它们可以运行数小时。

        所以总而言之,对您的数据进行测试并亲自查看。

        【讨论】:

          【解决方案4】:

          我赞同 Tom 的回答,即您应该选择一个更易于理解和维护的答案。

          任何数据库中的任何查询的查询计划都无法预测,因为您没有给我们索引或数据分布。预测哪个更快的唯一方法是针对您的数据库运行它们。

          根据经验,当我不需要在我的选择子句中包含任何来自 tblB 的列时,我倾向于使用子选择。当我想使用“in”谓词(通常用于您在问题中包含的“not in”)时,我肯定会选择子选择,原因很简单,当您或某人时这些更容易理解其他人已经回来并改变了他们。

          【讨论】:

            【解决方案5】:

            第一个查询在 SQL Server 中会更快,我认为这有点违反直觉 - 子查询 似乎 他们应该更慢。在某些情况下(随着数据量的增加)exists 可能比in 更快。

            【讨论】:

              【解决方案6】:

              需要注意的是,如果 TblB.a 不是唯一的,这些查询会产生不同的结果。

              【讨论】:

                【解决方案7】:

                根据我的观察,MSSQL 服务器为这些查询生成相同的查询计划。

                【讨论】:

                  【解决方案8】:

                  我创建了一个类似于 MSSQL2005 问题中的简单查询,但解释计划不同。第一个查询似乎更快。我不是 SQL 专家,但估计的解释计划有 37% 的查询 1 和 63% 的查询 2。看来查询 2 的最大成本是连接。两个查询都有两次表扫描。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2013-06-26
                    • 1970-01-01
                    • 1970-01-01
                    • 2015-06-20
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2018-06-09
                    相关资源
                    最近更新 更多