mac*_*ojw 28 sql performance join sql-server-2005
我想要在主表位于另一个表中的表中选择行.我不确定我是否应该在SQL Server 2005中使用JOIN或IN运算符.这两个SQL查询与大数据集(即数百万行)之间是否存在显着的性能差异?
SELECT *
FROM a
WHERE a.c IN (SELECT d FROM b)
SELECT a.*
FROM a JOIN b ON a.c = b.d
Run Code Online (Sandbox Code Playgroud)
Qua*_*noi 30
更新:
我的博客中的这篇文章总结了我的答案和我对另一个答案的评论,并显示了实际的执行计划:
SELECT *
FROM a
WHERE a.c IN (SELECT d FROM b)
SELECT a.*
FROM a
JOIN b
ON a.c = b.d
Run Code Online (Sandbox Code Playgroud)
这些查询不等同.如果您的表b不是密钥保留(即值b.d不唯一),它们可以产生不同的结果.
第一个查询的等效内容如下:
SELECT a.*
FROM a
JOIN (
SELECT DISTINCT d
FROM b
) bo
ON a.c = bo.d
Run Code Online (Sandbox Code Playgroud)
如果b.d是UNIQUE并且标记为(带有UNIQUE INDEX或UNIQUE CONSTRAINT),那么这些查询是相同的,并且很可能将使用相同的计划,因为SQL Server它足够聪明以考虑到这一点.
SQL Server 可以使用以下方法之一来运行此查询:
如果有一个索引a.c,dis UNIQUE和b相对较小a,那么条件会传播到子查询中并使用plain INNER JOIN(带有b前导)
如果有索引b.d而d不是UNIQUE,则该条件也会传播并被LEFT SEMI JOIN使用.它也可以用于上述条件.
如果有两个指标b.d,并a.c和他们是大,那么MERGE SEMI JOIN使用
如果任何表上都没有索引,则构建b并HASH SEMI JOIN使用哈希表.
这些方法都不是每次都重新评估整个子查询.
有关其工作原理的详细信息,请参阅我的博客中的此条目:
所有RDBMS四巨头都有链接.
都不是.使用ANSI-92 JOIN:
SELECT a.*
FROM a JOIN b a.c = b.d
Run Code Online (Sandbox Code Playgroud)
但是,它最好作为一个EXISTS
SELECT a.*
FROM a
WHERE EXISTS (SELECT * FROM b WHERE a.c = b.d)
Run Code Online (Sandbox Code Playgroud)
这将删除可能由JOIN生成的重复项,但如果不是更快则运行速度相同
根据 49,000,000 行表的经验,我建议使用 LEFT OUTER JOIN。使用 IN 或 EXISTS 需要 5 分钟才能完成,而 LEFT OUTER JOIN 在 1 秒内完成。
SELECT a.*
FROM a LEFT OUTER JOIN b ON a.c = b.d
WHERE b.d is not null -- Given b.d is a primary Key with index
Run Code Online (Sandbox Code Playgroud)
实际上,在我的查询中,我在 9 个表中执行此操作。
| 归档时间: |
|
| 查看次数: |
11742 次 |
| 最近记录: |