sql-server - SQL Server 2014执行计划创建需要很长时间(旧版本很快)

标签 sql-server tsql sql-server-2014

我在 SQL Server 2014 中遇到查询问题。第一次运行该查询时,需要很长时间才能生成执行计划。

奇怪的是,它在 SQL Server 的所有早期版本(2012、2008 R2、2008 等)中都运行良好。 似乎与所涉及的表上的唯一索引以及主查询中一定数量的子查询相结合有关。

以下是查询中涉及的表。与原始表格相比,我已经简化了表格很多,但问题仍然存在。请注意 table2 上的唯一约束,这似乎是导致问题的原因。无论是Table2上的唯一约束、唯一索引、甚至主键,结果都是一样的。

IF OBJECT_ID('Table2') IS NOT NULL DROP TABLE [Table2]
IF OBJECT_ID('Table1') IS NOT NULL DROP TABLE [Table1]
CREATE TABLE [dbo].[Table1] ( [ReferencedColumn] [int] NOT NULL PRIMARY KEY)
CREATE TABLE [dbo].[Table2] ( [ReferencedColumn] [int] NOT NULL FOREIGN KEY REFERENCES [Table1] ([ReferencedColumn]), [IntColumn] [int] NOT NULL, [AnotherIntColumn] [int] NULL )
CREATE UNIQUE NONCLUSTERED INDEX [IX_Table2] ON [dbo].[Table2] ([ReferencedColumn], [IntColumn])

如果我随后使用 select 语句中的索引从表中执行一些子查询,则第一次需要很长时间才能完成(在我的测试中超过 30 秒)。

SELECT  (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 1 ),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 2 ),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 3 ),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 4 ),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 5 ),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 6 ),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 7 ),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 8 ),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 9 ),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 10),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 11),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 12),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 13),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 14),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 15),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 16),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 17),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 18),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 19),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 20),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 21),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 22),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 23),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 24),
        (SELECT F2.IntColumn FROM Table2 F2 WHERE F2.[ReferencedColumn] = F.[ReferencedColumn] AND F2.IntColumn = 25)
FROM    Table1 F

由于表中没有行,并且查询在第一次运行后立即运行,因此在我看来,它一定是需要很长时间才能生成的执行计划。

但是,如果您执行下列更改之一,则会立即生成执行计划。

  • 删除索引
  • 删除索引的 UNIQUE 部分
  • 将 AnotherIntColumn 添加到索引
  • 将数据库的兼容性级别设置为 SQL Server 2012

值得注意的是,各个版本生成的执行计划都是相同的,只是生成的时间发生了变化。该计划包括许多“计算标量”操作,但我不认为当在 2012/2008 年立即生成相同的计划时会出现问题。

我只在 SQL Server 2014 Enterprise 和 Web 版本的几个实例上对其进行了测试,但我认为 2014 的其他版本也会出现相同的行为。

我已经有几种解决问题的方法(修改索引、更改兼容性级别、重写查询),但我很好奇为什么与旧版本的 SQL Server 相比性能下降如此之大?

最佳答案

SQL Server 2014 有 brand new Query Optimizer 。基数估计(猜测语句将返回多少行)比过去的版本更加激进。在某些错误和边缘情况下,新优化器将需要更长的时间才能找到最佳查询计划。设置较低的兼容性级别会回退到以前的查询优化器。

您的查询几乎是一个折磨测试。有更好的方法来编写它。但我认为您在新的查询优化器中暴露了一个错误。在 SQL Connect 上提交错误报告.

关于sql-server - SQL Server 2014执行计划创建需要很长时间(旧版本很快),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26177480/

相关文章:

sql-server - 英文和中文文本的文件编码

SQL Server - "sys.functions"在哪里?

sql - T-SQL UPDATE 中的每一行的 RAND 不不同

sql - 如何从单行创建多行-标准化表

c# - 在 C# 窗体中将密码存储更改为哈希存储

sql - 如何从 SQL Server 2014 中的选择查询将数据分配给用户定义的表类型

sql - 合并查询中按月和年排序

sql-server - 还原问题 SQL Server 版本?

sql - 非规范化数据(也许是一个枢轴?)

sql - 如果函数不存在则创建一个函数,如果函数已经存在则更改函数