假设我们有一个基本上使用联合将2个记录集合并为1的查询。现在,我需要通过使用连接来复制记录。我认为选项1在我看来是出于性能原因最好的选择,但是想知道SQL查询专家的想法。
基本上,我“知道”答案是“1”。但是,我也想知道,我可能是错的 - 我可能会错过这方面的一面吗?
(SQL Server) 以下是我的选择。
伪代码
原始查询:
Select Name, Category from t1
Union
Select Name, Category from t2
选项1)
Select Name, Category from t1
Inner Join (here)
Union
Select Name, Category from t2
Same inner Join (here)
选项2)
Select * from (
Select Name, Category from t1
Union
Select Name, Category from t2
) t
(Inner Join Here)
答案 0 :(得分:5)
SELECT Name, Category
FROM t1
JOIN t_right
ON right_category = category
UNION
SELECT Name, Category
FROM t2
JOIN t_right
ON right_category = category
SELECT *
FROM (
SELECT Name, Category
FROM t1
UNION
SELECT Name, Category
FROM t2
) t
JOIN t_right
ON right_category = category
这些查询不相同:如果右表中的两个以上记录可以满足连接条件,则第二个查询可以返回重复项,如下所示:
t1
Name Category
--- ---
Apple 1
t2
Name Category
--- ---
Apple 1
t_right
Category
---
1
1
第一个查询将返回Apple, 1
一次,第二个查询将返回两次。
在性能方面,在我们看到您的数据之前,很难确定哪个查询会更有效:
第一个选项可以通过对每个查询应用不同的算法来提高效率。
第二个选项只能通过阅读一次右表来提高效率。
作为一个非常粗略的经验法则,如果连接条件在t1
和t2
上具有选择性,则第一个选项将更有效,而如果不是,则第二个选项将更有效。
但是,在简单的情况下(在具有很少高基数值的可搜索条件下的连接)SQL Server
的优化器会将连接推出子查询,以便它与以下查询相同:< / p>
SELECT Name, Category
FROM t_right
CROSS APPLY
(
SELECT Name, Category
FROM t1
WHERE t1.Category = t_right.category
UNION
SELECT Name, Category
FROM t2
WHERE t2.Category = t_right.category
) t
答案 1 :(得分:1)
在这种情况下,有几个不同因素会影响性能。例如,可能首先将它放入一个临时表(从子查询中进行联合),因为必须进行两次索引扫描才能进行两次索引扫描。
我们可以整天喋喋不休,但是......简单回答:测试每一个,看看哪个有最有效的查询计划和/或最佳执行时间。这是真正说出来的唯一方法。
答案 2 :(得分:0)
作为基线,我选择选项2,因为 - 如果其他条件相同(总有特殊情况和例外情况) - 它应该更快。
在选项1中,您读取t1,然后通过读取加入到“here”,然后读取t2,然后加入另一个读取到“here”,然后将它们组合在一起。
在选项2中,您读取t2,然后读取t2,将它们连接在一起,然后将合并的集合(不同或不同,取决于UNION ALL的使用)加入“here”。
换句话说,在选项1中,您可以两次读取“here”表,在选项2中读取一次。它可能是内存中表格中的一行,但它仍然是一个读取。
答案 3 :(得分:0)
在简单的情况下,选项二更好,因为表“(内连接)”上的索引搜索将完成一次。