SQL Server语言 - 多个 UNION ALL 的速度慢得令人难以忍受



一点背景:

我们正在迁移到一个新的SQL服务器,它的规格比旧的要高得多,并且包括新版本的SSMS(2014)。

有一种视图每天被无数次使用。在旧服务器上运行时,它始终需要大约 1 分 30 秒,而在新服务器上则需要更长的时间;通常5分钟左右。

SELECT v1.*
FROM view1 v1
    UNION ALL
SELECT v2.*
FROM view2 v2
    UNION ALL
SELECT v3.*
FROM view3 v3

我发现在新服务器上,如果我只使用一个 UNION ALL 和两个视图,查询将在几秒钟内执行。 例如,以下两项将在 10 秒内成功执行。

SELECT v1.* 
FROM view1 v1
    UNION ALL
SELECT v2.*
FROM view2 v2

SELECT v2.*
FROM view2 v2
    UNION ALL
SELECT v3.*
FROM view3 v3

但是,一旦我将额外的 UNION ALL 添加到语句中以包含第三个视图,查询大约需要 5 分钟。

视图本身不是问题,因为在旧服务器上它运行良好。新服务器上是否有一些我可能缺少的设置可能会加快速度?

提前谢谢。

更新

我注意到,这并不是因为使用 UNION ALL 组合了三个视图,事实上,它归结为两个特定的视图,这两个视图需要很长时间才能将 UNION ALL 放在一起。解释一下:

SELECT v1.* FROM view1 v1
UNION ALL
SELECT v2.* FROM view2 v2

SELECT v2.* FROM view2 v2
UNION ALL
SELECT v3.* FROM view3 v3

两者都在 10 秒内执行,但以下需要 5 分钟才能执行。

SELECT v1.* FROM view1 v1
UNION ALL
SELECT v3.* FROM view3 v3
这不是由于返回的行

数,因为返回最多行数(~3500 行)的视图是慢速 UNION ALL 语句 view2 中实际省略的视图。其他两个视图分别返回大约 400 行。

那么,这是数据的问题吗?在这两种观点中,我应该寻找什么吗?

问题——

很可能——不在于union all,而在于观点。视图在查询中首次调用时进行编译。如果基础数据发生变化,则执行计划可能不会更改。

您应该比较两台服务器上的执行计划。然后,您应该在两台服务器上重新编译查询。

如果这样做可行,您可能希望设置一个每晚重新编译视图的作业,以确保执行计划与基础数据保持同步。

>SQL Server 2014有一个全新的基数估计器,这意味着你可能会得到与旧版本不同的执行计划。您可以尝试在查询末尾添加 OPTION(QUERYTRACEON 9481),以强制使用旧版本的 CE。

如果它有帮助 - 那就是问题所在。如果没有 - 继续寻找(你能发布执行计划吗?

我设法在大约 15 秒内完成这项工作; 极快!

下面的链接记录了一个问题,即由于严重高估返回的行数,某些复杂查询在新的 SQL Server 2014 基数估算器中运行速度要慢得多。最后,解决方案是将跟踪标志 4199 添加到查询中,这解决了问题。

https://blogs.msdn.microsoft.com/psssql/2015/06/16/identifying-sql-server-2014-new-cardinality-estimator-issues-and-service-pack-1-improvement/

SELECT v1.*
FROM view1 v1
    UNION ALL
SELECT v2.*
FROM view2 v2
    UNION ALL
SELECT v3.*
FROM view3 v3
OPTION (QUERYTRACEON 4199)

最新更新