例如,我想获取应用了某些标签的所有项目的列表。我可以做以下任何一种情况:
SELECT Item.ID, Item.Name
FROM Item
WHERE Item.ID IN (
SELECT ItemTag.ItemID
FROM ItemTag
WHERE ItemTag.TagID = 57 OR ItemTag.TagID = 55)
或者
SELECT Item.ID, Item.Name
FROM Item
LEFT JOIN ItemTag ON ItemTag.ItemID = Item.ID
WHERE ItemTag.TagID = 57 OR ItemTag.TagID = 55
GROUP BY Item.ID, Item.Name
或完全不同的东西。
一般来说(假设有一般规则),什么是更有效的方法?
答案 0 :(得分:17)
SELECT Item.ID, Item.Name FROM Item WHERE Item.ID IN ( SELECT ItemTag.ItemID FROM ItemTag WHERE ItemTag.TagID = 57 OR ItemTag.TagID = 55)
或
SELECT Item.ID, Item.Name FROM Item LEFT JOIN ItemTag ON ItemTag.ItemID = Item.ID WHERE ItemTag.TagID = 57 OR ItemTag.TagID = 55 GROUP BY Item.ID
您的第二个查询将无法编译,因为它引用了Item.Name
而没有对其进行分组或聚合。
如果我们从查询中删除GROUP BY
:
SELECT Item.ID, Item.Name
FROM Item
JOIN ItemTag
ON ItemTag.ItemID = Item.ID
WHERE ItemTag.TagID = 57 OR ItemTag.TagID = 55
这些仍然是不同的查询,除非ItemTag.ItemId
是UNIQUE
密钥并标记为此类。
SQL Server
能够检测IN
列上的UNIQUE
条件,并将IN
条件转换为JOIN
。
如果ItemTag.ItemID
不是UNIQUE
,则第一个查询将使用一种SEMI JOIN
算法,这种算法在SQL Server
中非常有效。
您可以将第二个查询转换为JOIN
:
SELECT Item.ID, Item.Name
FROM Item
JOIN (
SELECT DISTINCT ItemID
FROMT ItemTag
WHERE ItemTag.TagID = 57 OR ItemTag.TagID = 55
) tags
ON tags.ItemID = Item.ID
但是这个效率低于IN
或EXISTS
。
在我的博客中查看此文章,以获得更详细的性能比较:
答案 1 :(得分:4)
我认为这取决于优化器如何处理它们,甚至可能是你最终获得相同性能的情况。显示执行计划是你的朋友。
答案 2 :(得分:2)
SELECT Item.ID, Item.Name
...
GROUP BY Item.ID
这不是有效的T-SQL。 Item.Name必须出现在group by子句中或聚合函数中,例如SUM或MAX。
答案 3 :(得分:1)
几乎不可能(除非你是那些疯狂的大师DBA之一)在不查看执行计划和/或运行压力测试的情况下告诉什么是快速的,什么是不会。
答案 4 :(得分:0)
运行这个:
SET SHOWPLAN_ALL ON
然后运行查询的每个版本
您可以看到他们是否返回相同的计划,如果没有查看每个计划的第一行的TotalSubtreeCost,看看它们有多么不同。
答案 5 :(得分:0)
性能似乎总是得到投票,但你也听到“购买硬件比程序员更便宜”
第二场胜利表现。
有时看看SQL并了解其目的很好,但这就是评论的用途。第一个查询是使用另一个表进行过滤 - 非常简单。
第二个使用distinct而不是group by更有意义(从理解目的而非性能)。我希望有些聚合在select中,但是没有。速度杀死。
答案 6 :(得分:0)
第二个在MySQL中效率更高。对于每个WHERE条件测试,MySQL都会在IN语句中重新执行查询。