查询在UNION之前或之后加入的性能

时间:2009-10-28 13:50:04

标签: sql sql-server tsql

假设我们有一个基本上使用联合将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)

4 个答案:

答案 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一次,第二个查询将返回两次。

在性能方面,在我们看到您的数据之前,很难确定哪个查询会更有效:

  • 第一个选项可以通过对每个查询应用不同的算法来提高效率。

  • 第二个选项只能通过阅读一次右表来提高效率。

作为一个非常粗略的经验法则,如果连接条件在t1t2上具有选择性,则第一个选项将更有效,而如果不是,则第二个选项将更有效。

但是,在简单的情况下(在具有很少高基数值的可搜索条件下的连接)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)

在简单的情况下,选项二更好,因为表“(内连接)”上的索引搜索将完成一次。