请记住这两种类型的查询:
--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'
执行计划是:
两者相同且 50%
答案 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;记录,然后组合这些结果,您将为以后的修订准备查询,这可能使优化程序的选择无效,从而导致相同的执行计划。
简而言之,您不必强制简单查询是最佳的,但这是一个好习惯,并且在创建更复杂的查询时会有所帮助。