SQL加入Vs SQL子查询(性能)?

我想知道我是否有这样的连接查询 -

Select E.Id,E.Name from Employee E join Dept D on E.DeptId=D.Id

和这样的子查询 -

Select E.Id,E.Name from Employee Where DeptId in (Select Id from Dept)

当我考虑性能时,哪两个查询会更快,为什么?

还有一段时间我应该更喜欢一个吗?

对不起,如果这是太微不足道,以前问过,但我很困惑。 此外,如果你们可以建议我用来测量两个查询的性能的工具,那将是很棒的。 非常感谢!

Vishal asked 2019-08-12T16:10:04Z
8个解决方案
42 votes

我希望第一个查询更快,主要是因为你有一个等价和一个显式的JOIN。 根据我的经验,IN是一个非常慢的运算符,因为SQL通常将其计算为由" OR"分隔的一系列WHERE子句。(WHERE x=Y OR x=Z OR...)。

与ALL THINGS SQL一样,您的里程可能会有所不同。 速度将在很大程度上取决于索引(你在两个ID列上都有索引吗?这将有很多帮助...)等等。

100%确定性更快的唯一真实方法是打开性能跟踪(IO统计特别有用)并运行它们。 确保在运行之间清除缓存!

JNK answered 2019-08-12T16:10:33Z
27 votes

嗯,我相信它是一个旧的但是黄金" 题。 答案是:"这取决于!"。表演是一个如此微妙的主题,它说太傻了:"永远不要使用子查询,总是加入"。在以下链接中,您将找到一些我发现非常有用的基本最佳实践:这里1这里2这里3

我有一个50000元素的表,我正在寻找的结果是739元素。

我的查询起初是这样的:

SELECT  p.id,
    p.fixedId,
    p.azienda_id,
    p.categoria_id,
    p.linea,
    p.tipo,
    p.nome
FROM prodotto p
WHERE p.azienda_id = 2699 AND p.anno = (
    SELECT MAX(p2.anno) 
    FROM prodotto p2 
    WHERE p2.fixedId = p.fixedId 
)

执行需要7.9秒。

我的查询最后是这样的:

SELECT  p.id,
    p.fixedId,
    p.azienda_id,
    p.categoria_id,
    p.linea,
    p.tipo,
    p.nome
FROM prodotto p
WHERE p.azienda_id = 2699 AND (p.fixedId, p.anno) IN
(
    SELECT p2.fixedId, MAX(p2.anno)
    FROM prodotto p2
    WHERE p.azienda_id = p2.azienda_id
    GROUP BY p2.fixedId
)

花了0.0256s

好SQL,好。

linuxatico answered 2019-08-12T16:11:49Z
9 votes

开始查看执行计划,以了解SQl Server如何解释它们的差异。 您还可以使用Profiler实际多次运行查询并获得不同。

我不希望它们如此可怕地不同,在使用相关子查询时,使用连接而不是子查询可以获得真正的大量性能提升。

EXISTS通常比这两者中的任何一个更好,当你在谈论左连接时你想要的所有记录都不在左连接表中,那么NOT EXISTS通常是一个更好的选择。

HLGEM answered 2019-08-12T16:12:32Z
4 votes

这两个查询可能在语义上不相同。 如果一个员工在一个以上的部门工作(可能在我工作的企业;可以肯定,这意味着你的表没有完全规范化),那么第一个查询将返回重复的行,而第二个查询则不会。 要在这种情况下使查询等效,必须将DISTINCT关键字添加到OrgChart子句中,这可能会对性能产生影响。

请注意,有一个设计经验法则规定表应该为实体/类或实体/类之间的关系建模,但不能同时建模。 因此,我建议您创建第三个表,例如OrgChart,以模拟员工和部门之间的关系。

onedaywhen answered 2019-08-12T16:13:08Z
4 votes

性能取决于您正在执行的数据量...

如果是20k左右的数据较少。 JOIN效果更好。

如果数据更像是100k +那么IN效果更好。

如果你不需要来自另一个表的数据,那么IN是好的,但是最好去EXISTS。

我测试的所有这些标准和表格都有适当的索引。

JP Emvia answered 2019-08-12T16:14:04Z
3 votes

表现应该是一样的; 在表上应用正确的索引和聚类更为重要(在该主题上存在一些好的资源)。

(编辑以反映更新的问题)

Lucero answered 2019-08-12T16:14:39Z
1 votes

我知道这是一篇很老的帖子,但我认为这是一个非常重要的话题,特别是现在我们有10M +记录并谈论数TB的数据。

我还将重点介绍以下观察结果。 我的表中有大约45M的记录([data]),我的[cats]表中有大约300条记录。 我对所有要讨论的查询都有广泛的索引。

考虑示例1:

UPDATE d set category = c.categoryname
FROM [data] d
JOIN [cats] c on c.id = d.catid

与例2:

UPDATE d set category = (SELECT TOP(1) c.categoryname FROM [cats] c where c.id = d.catid)
FROM [data] d

实施例1运行约23分钟。 实施例2花费约5分钟。

所以我会得出结论,在这种情况下子查询要快得多。 当然要记住我使用的M.2 SSD驱动器能够支持i / o @ 1GB / sec(那个字节而不是位),所以我的索引也非常快。 因此,在您的环境中,这也可能会影响速度

如果它是一次性数据清理,可能最好只是让它运行和完成。 我使用TOP(10000)并查看它需要多长时间并乘以大型查询之前的记录数。

如果您正在优化生产数据库,我强烈建议预处理数据,即使用触发器或作业代理到异步更新记录,以便实时访问检索静态数据。

Arvin Amir answered 2019-08-12T16:16:02Z
0 votes

您可以使用解释计划来获得客观答案。

对于您的问题,Exists过滤器可能执行速度最快。

Snekse answered 2019-08-12T16:16:35Z
translate from https://stackoverflow.com:/questions/3856164/sql-joins-vs-sql-subqueries-performance