subselect vs outer join

时间:2008-09-06 13:05:43

标签: sql sql-server database performance

考虑以下两个问题:

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

哪个会表现更好?我的假设是,通常连接会更好,除非子选择返回非常小的结果集。

8 个答案:

答案 0 :(得分:16)

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

我建议选择更清晰,更容易维护的那个,对于我的钱,这是第一个。调试子查询要容易得多,因为它可以独立运行以检查是否合理。

答案 1 :(得分:4)

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

答案 2 :(得分:3)

嗯,这取决于数据集。根据我的经验,如果你有一个小的数据集,那么如果它很大就去左边加入NOT IN。对于大型数据集,NOT IN子句似乎非常慢。

我可能补充的另一件事是解释计划可能会产生误导。我已经看过几个查询,其中解释是天高,查询运行在1s以下。另一方面,我看到了具有出色解释计划的查询,并且可以运行数小时。

所以总而言之,测试你的数据并亲自看看。

答案 3 :(得分:2)

我是汤姆的回答,你应该选择一个更容易理解和维护的答案。

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

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

答案 4 :(得分:1)

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

答案 5 :(得分:1)

应该注意,如果TblB.a不是唯一的,这些查询将产生不同的结果。

答案 6 :(得分:0)

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

答案 7 :(得分:0)

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