我想知道我是否有加入查询 -
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)
当我考虑性能时,哪两个查询会更快,而为什么?
还有一段时间我应该更喜欢一个吗?
很抱歉,如果这太过琐碎并且之前被问过,但我很困惑。此外,如果你们可以建议我使用工具来测量两个查询的性能,那就太好了。非常感谢!
答案 0 :(得分:42)
我希望第一个查询更快,主要是因为你有一个等价和一个显式的JOIN。根据我的经验,IN
是一个非常慢的运算符,因为SQL通常将它评估为由“OR”(WHERE
)分隔的一系列WHERE x=Y OR x=Z OR...
子句。
与ALL THINGS SQL一样,您的里程可能会有所不同。速度将在很大程度上取决于索引(你在两个ID列上都有索引吗?这将有很多帮助...)等等。
唯一能够100%确定性更快的方法是打开性能跟踪(IO统计特别有用)并同时运行它们。确保在运行之间清除缓存!
答案 1 :(得分:28)
嗯,我相信这是一个“老而金”的问题。答案是:“这取决于!”。 演出是如此微妙的主题,说:“永远不要使用子查询,永远加入”是太愚蠢了。 在以下链接中,您将找到一些我发现非常有用的基本最佳实践: Here 1 Here 2 Here 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,好。
答案 2 :(得分:9)
开始查看执行计划,了解SQl Server如何解释它们的不同之处。您还可以使用Profiler多次实际运行查询并获得不同。
我不希望这些变得非常不同,在使用相关子查询时,使用连接而不是子查询可以获得真正的大量性能提升。
EXISTS通常比这两者中的任何一个更好,当你在谈论左连接时你想要的所有记录都不在左连接表中,那么NOT EXISTS通常是一个更好的选择。
答案 3 :(得分:4)
这两个查询可能在语义上不相同。如果一个员工在一个以上的部门工作(可能在我工作的企业;可以肯定,这意味着你的表没有完全规范化),那么第一个查询将返回重复行,而第二个查询则不会。要在这种情况下使查询等效,必须将DISTINCT
关键字添加到SELECT
子句中,这可能会对性能产生影响。
请注意,有一个设计经验法则规定表应该为实体/类或实体/类之间的关系建模,但不能同时建模。因此,我建议您创建第三个表格,例如OrgChart
,以模拟员工与部门之间的关系。
答案 4 :(得分:4)
效果取决于您正在执行的数据量......
如果它的数据少于20k左右。 JOIN效果更好。
如果数据更像是100k +,则IN工作得更好。
如果你不需要来自另一个表的数据,IN很好,但是最好去EXISTS。
我测试的所有这些标准和表格都有适当的索引。
答案 5 :(得分:3)
表现应该是一样的;在表上应用正确的索引和聚类更为重要(该主题上存在some good resources)。
(编辑以反映更新后的问题)
答案 6 :(得分:1)
我知道这是一篇过时的文章,但是我认为这是一个非常重要的话题,尤其是在当今拥有1000万条以上记录并谈论数TB数据的情况下。
我还将强调以下几点。我的表([数据])中有大约4500万条记录,[猫]表中有大约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分钟。
因此,我可以得出结论,这种情况下的子查询要快得多。当然,请记住,我正在使用I / o @ 1GB / sec(即字节而不是位)的M.2 SSD驱动器,因此索引的速度也非常快。因此,这可能也会影响您的速度
如果一次性清理数据,则最好让它运行并完成。我使用TOP(10000)来查看花费多长时间并乘以记录数,然后再执行大查询。
如果您正在优化生产数据库,我强烈建议您预处理数据,即使用触发器或作业代理来异步更新记录,以便实时访问检索静态数据。
答案 7 :(得分:0)
您可以使用解释计划来获得客观答案。
对于您的问题,an Exists filter可能会执行得最快。