使用'然后联盟'或使用' Union然后'

时间:2015-03-17 12:29:04

标签: sql-server performance union rdbms query-performance

请记住这两种类型的查询:

--query1
Select someFields
From someTables
Where someWhereClues
Union all
Select someFields
FROM some Tables
Where someWhereClues

--query2
Select * FROM (
    Select someFields 
    From someTables
    Union all 
    Select someFields
    FROM someTables
    ) DT
Where someMixedWhereClues
  

注意:
  在两个查询中,最终结果字段都相同

我认为是第一个。查询速度更快或性能更好! 但经过一些研究后,我对此note感到困惑:

  

SQL Server(作为RDBMS的示例)首先读取整个数据然后查找记录。 =>所以在两个查询中,所有记录都会读取和搜索。

请帮助我解决我的误解,以及query1和query2之间是否还有其他差异?


修改:添加样本计划:

select t.Name, t.type from sys.tables t where t.type = 'U'
union all
select t.Name, t.type from sys.objects t where t.type = 'U'

select * from (
    select t.Name, t.type from sys.tables t
    union all
    select t.Name, t.type from sys.objects t
    ) dt
where dt.type = 'U'

执行计划是: enter image description here enter image description here

  

两者相同且 50%

6 个答案:

答案 0 :(得分:5)

SQL Server query optimizer优化了两个查询,因此您可以获得几乎相同的效果。

答案 1 :(得分:1)

第一个不能慢。这是推理:

  • 如果第一个中的WHERE条款可以有效地使用INDEX,则UNION中要收集的行数将会减少。行数越少 - >更快。
  • 第二个INDEX上没有UNION,因此无法以此方式优化WHERE

以下是可能导致第一个变慢的事情。但我认为它们是例外,而不是规则。

  • 实现了不同的并行度。
  • 在您运行查询时,会缓存不同的内容。

警告:我假设所有三个WHERE条款都相同(如您的示例所示)。

答案 2 :(得分:1)

根据经验,我将始终考虑使用第一种类型的查询。

在简化WHERE谓词的简化样本和查询中,两者都将使用相同的计划。但是在更复杂的查询中,对于更复杂的谓词,优化器可能无法为第二类查询提供同样有效的解决方案(它只是优化器,并受到约束资源和时间限制)。查询越复杂,优化器找到最佳执行计划的可能性就越小(因为它最终将超时并选择到目前为止发现的最差计划)。如果谓词是ORed,它会变得更糟。

答案 3 :(得分:0)

在我的练习中,第一个选项从不慢于第二个选项。我认为优化器足够聪明,可以以相同的方式或多或少地优化这些计划。但是我做了一些测试,第一个选项总是更好。例如:

CREATE TABLE #a ( a INT, b INT );

WITH Numbers ( I ) AS (
    SELECT 1000

    UNION ALL

    SELECT I + 1
    FROM Numbers
    WHERE I < 5000
)
INSERT INTO #a ( a )
SELECT I
FROM Numbers
ORDER BY CRYPT_GEN_RANDOM(4)
OPTION ( MAXRECURSION 0 );

WITH Numbers ( I ) AS (
    SELECT 1000

    UNION ALL

    SELECT I + 1
    FROM Numbers
    WHERE I < 5000
)
INSERT INTO #a ( b )
SELECT I
FROM Numbers
ORDER BY CRYPT_GEN_RANDOM(4)
OPTION ( MAXRECURSION 0 );

SELECT a, b
FROM #a
WHERE a IS NOT NULL
UNION ALL
SELECT a, b
FROM #a
WHERE b IS NOT NULL

SELECT *
FROM (
    SELECT a, b
    FROM #a
    UNION ALL
    SELECT a, b
    FROM #a
    ) c
WHERE a IS NOT NULL
    OR b IS NOT NULL

结果为47%vs 53%

答案 4 :(得分:0)

根据我的经验,对此没有直接的答案,它根据基础查询的性质而有所不同。如您所示,优化程序在这两种情况下都会提供相同的执行计划,但情况并非总是如此。性能通常类似,但有时性能可能会根据查询而有很大差异。一般来说,只有在没有充分理由的情况下表现不好时,我才会仔细研究它。

答案 5 :(得分:0)

SQLServer会将这两个查询优化为相同的内容,如您发布的执行计划中所示。它能够做到这一点,因为在这种情况下查询相当简单;在另一种情况下,它可能会有不同的结果。只要您编写查询,就应该尝试遵循优化程序执行的相同通用规则,并尽快过滤以限制返回的结果集。通过告诉它你首先想要得到的只是&#39; U&#39;记录,然后组合这些结果,您将为以后的修订准备查询,这可能使优化程序的选择无效,从而导致相同的执行计划。

简而言之,您不必强制简单查询是最佳的,但这是一个好习惯,并且在创建更复杂的查询时会有所帮助。