SQL Server 2014执行计划创建需要很长时间(在旧版本中快速)

时间:2014-10-03 10:40:36

标签: sql-server tsql sql-server-2014

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

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

以下是查询中涉及的表。与原件相比,我对表格进行了大量简化,但问题仍然存在。注意table2上的唯一约束,这似乎是导致问题的原因。如果它是表2中的唯一约束,唯一索引或甚至主键并不重要,结果是相同的。

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

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

但是,如果您执行下面列出的其中一项更改,则会立即生成执行计划。

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

值得注意的是,生成的执行计划在各个版本中是相同的,只有生成它的时间会发生变化。该计划包括许多" Compute Scalar"在2012/2008年立即生成相同的计划时,我不知道怎么会出现问题。

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

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

1 个答案:

答案 0 :(得分:2)

SQL Server 2014有一个brand new Query Optimizer。基数估计(猜测语句将返回多少行)比过去版本更具攻击性。有一些错误和边缘情况,新的优化器需要更长的时间才能找到最佳的查询计划。设置较低的兼容级别可以追溯到之前的查询优化程序。

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