Vis*_*hal 100 sql performance join subquery sql-server-2008
我想知道我是否有这样的连接查询 -
Select E.Id,E.Name from Employee E join Dept D on E.DeptId=D.Id
Run Code Online (Sandbox Code Playgroud)
和这样的子查询 -
Select E.Id,E.Name from Employee Where DeptId in (Select Id from Dept)
Run Code Online (Sandbox Code Playgroud)
当我考虑性能时,哪两个查询会更快,为什么?
还有一段时间我应该更喜欢一个吗?
对不起,如果这是太微不足道,以前问过,但我很困惑.此外,如果你们可以建议我用来测量两个查询的性能的工具,那将是很棒的.非常感谢!
JNK*_*JNK 45
我希望第一个查询更快,主要是因为你有一个等价和一个显式的JOIN.根据我的经验,IN
运算符非常慢,因为SQL通常将其作为一系列WHERE
由"OR"(WHERE x=Y OR x=Z OR...
)分隔的子句进行计算.
与ALL THINGS SQL一样,您的里程可能会有所不同.速度将在很大程度上取决于索引(你在两个ID列上都有索引吗?这将有很多帮助...)等等.
100%确定性更快的唯一真实方法是打开性能跟踪(IO统计特别有用)并运行它们.确保在运行之间清除缓存!
lin*_*ico 35
好吧,我相信这是一个"老而金"的问题.答案是:"这取决于!".演出是如此微妙的主题,说:"永远不要使用子查询,永远加入"是太愚蠢了.在以下链接中,您将找到一些我发现非常有用的基本最佳实践: 这里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
)
Run Code Online (Sandbox Code Playgroud)
执行需要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
)
Run Code Online (Sandbox Code Playgroud)
花了0.0256s
好SQL,好.
HLG*_*GEM 10
开始查看执行计划,以了解SQl Server如何解释它们的差异.您还可以使用Profiler实际多次运行查询并获得不同.
我不希望它们如此可怕地不同,在使用相关子查询时,使用连接而不是子查询可以获得真正的大量性能提升.
EXISTS通常比这两者中的任何一个更好,当你在谈论左连接时你想要的所有记录都不在左连接表中,那么NOT EXISTS通常是一个更好的选择.
小智 8
性能取决于您正在执行的数据量...
如果较少,则大约20k的数据。JOIN效果更好。
如果数据更像是100k +,那么IN工作得更好。
如果您不需要其他表中的数据,则IN很好,但是最好使用EXISTS。
我测试的所有这些条件和表均具有正确的索引。
我知道这是一篇旧文章,但我认为这是一个非常重要的主题,尤其是现在我们拥有 10M+ 记录并谈论 TB 级数据。
我还将阐述以下观点。我的表 ([data]) 中有大约 45M 条记录,[cats] 表中有大约 300 条记录。我为我将要讨论的所有查询建立了广泛的索引。
考虑示例 1:
UPDATE d set category = c.categoryname
FROM [data] d
JOIN [cats] c on c.id = d.catid
Run Code Online (Sandbox Code Playgroud)
与示例 2 相比:
UPDATE d set category = (SELECT TOP(1) c.categoryname FROM [cats] c where c.id = d.catid)
FROM [data] d
Run Code Online (Sandbox Code Playgroud)
示例 1 的运行时间约为 23 分钟。示例 2 大约需要 5 分钟。
所以我得出结论,在这种情况下子查询要快得多。当然,请记住,我使用的 M.2 SSD 驱动器具有 I/O @ 1GB/秒(这是字节而不是位),因此我的索引也非常快。所以这也可能会影响您的情况的速度
如果是一次性数据清理,最好让它运行并完成。我使用 TOP(10000) 并查看在执行大查询之前需要多长时间并乘以记录数。
如果您正在优化生产数据库,我强烈建议对数据进行预处理,即使用触发器或作业代理来异步更新记录,以便实时访问检索静态数据。
这两个查询在语义上可能不相同。如果一名员工为多个部门工作(可能在我工作的企业中;不可否认,这意味着您的表未完全规范化),那么第一个查询将返回重复的行,而第二个查询则不会。为了使查询在这种情况下等效,DISTINCT
必须将关键字添加到SELECT
子句中,这可能会对性能产生影响。
请注意,有一条设计经验法则规定表应该对实体/类或实体/类之间的关系进行建模,但不能同时对两者进行建模。因此,我建议您创建第三个表,例如OrgChart
,来模拟员工和部门之间的关系。