Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/silverlight/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 从SQLServer2008升级到SQLServer2016后,原来快的存储过程现在变慢了_Performance_Sql Server 2008_Stored Procedures_Common Table Expression_Sql Server 2016 - Fatal编程技术网

Performance 从SQLServer2008升级到SQLServer2016后,原来快的存储过程现在变慢了

Performance 从SQLServer2008升级到SQLServer2016后,原来快的存储过程现在变慢了,performance,sql-server-2008,stored-procedures,common-table-expression,sql-server-2016,Performance,Sql Server 2008,Stored Procedures,Common Table Expression,Sql Server 2016,我们有一个存储过程,它返回属于地理空间区域(“地理”)的所有记录。它使用一个CTE(with)、一些联合、一些内部联接,并以XML的形式返回数据;没有争议或前沿,但也不是微不足道的 多年来,这个存储过程在SQLServer2008上为我们提供了良好的服务。它在一个相对较慢的服务器上运行了1秒。我们刚刚在一台拥有大量内存和超高速SDD的超高速服务器上迁移到SQL Server 2016 整个数据库和相关应用程序在这个新服务器上运行得非常快,我们对此非常满意。但是,这一存储过程的运行时间是16秒,而

我们有一个存储过程,它返回属于地理空间区域(“地理”)的所有记录。它使用一个CTE(with)、一些联合、一些内部联接,并以XML的形式返回数据;没有争议或前沿,但也不是微不足道的

多年来,这个存储过程在SQLServer2008上为我们提供了良好的服务。它在一个相对较慢的服务器上运行了1秒。我们刚刚在一台拥有大量内存和超高速SDD的超高速服务器上迁移到SQL Server 2016

整个数据库和相关应用程序在这个新服务器上运行得非常快,我们对此非常满意。但是,这一存储过程的运行时间是16秒,而不是1秒——针对完全相同的参数和完全相同的数据集

我们已经更新了这个数据库的索引和统计数据。我们还将数据库的兼容性级别从100更改为130

有趣的是,我重新编写了存储过程以使用临时表和“insert”,而不是使用CTE。这使时间从16秒减少到4秒

执行计划没有提供任何关于瓶颈位置的明显见解

我们对想法有点迷恋。我们下一步该怎么办?提前谢谢

--

我现在花在这个问题上的时间比我愿意承认的要多。我将存储过程简化为以下查询,以演示该问题

drop table #T 

declare @viewport sys.geography=convert(sys.geography,0xE610000001041700000000CE08C22D7740C002370B7670F4624000CE08C22D7740C002378B5976F4624000CE08C22D7740C003370B3D7CF4624000CE08C22D7740C003378B2082F4624000CE08C22D7740C003370B0488F4624000CE08C22D7740C004378BE78DF4624000CE08C22D7740C004370BCB93F4624000CE08C22D7740C004378BAE99F4624000CE08C22D7740C005370B929FF4624000CE08C22D7740C005378B75A5F4624000CE08C22D7740C005370B59ABF462406F22B7698E7640C005370B59ABF462406F22B7698E7640C005378B75A5F462406F22B7698E7640C005370B929FF462406F22B7698E7640C004378BAE99F462406F22B7698E7640C004370BCB93F462406F22B7698E7640C004378BE78DF462406F22B7698E7640C003370B0488F462406F22B7698E7640C003378B2082F462406F22B7698E7640C003370B3D7CF462406F22B7698E7640C002378B5976F462406F22B7698E7640C002370B7670F4624000CE08C22D7740C002370B7670F4624001000000020000000001000000FFFFFFFF0000000003)

declare @outputControlParameter nvarchar(max) = 'a value passed in through a parameter to the stored that controls the nature of data to return. This is not the solution you are looking for'

create table #T
    (value int)

insert into #T 
select 136561 union 
select 16482 -- These values are sourced from parameters into the stored proc

select 
      [GeoServices_Location].[GeographicServicesGatewayId],
      [GeoServices_Location].[Coordinate].Lat,
      [GeoServices_Location].[Coordinate].Long

      from GeoServices_Location

      inner join GeoServices_GeographicServicesGateway
            on    GeoServices_Location.GeographicServicesGatewayId = GeoServices_GeographicServicesGateway.GeographicServicesGatewayId

      where 
        (
            (len(@outputControlParameter) > 0 and GeoServices_Location.GeographicServicesGatewayId in (select value from #T)) 
            or (len(@outputControlParameter) = 0 and GeoServices_Location.Coordinate.STIntersects(@viewport) = 1)
        )
        and GeoServices_GeographicServicesGateway.PrimarilyFoundOnLayerId IN (3,8,9,5) 

GO
存储过程归结起来就是这样,它在SQL Server 2008上运行0秒,在SQL Server 2016上运行5秒

Windows Server 2016因地理空间交叉呼叫而受阻,94%的时间都花在那里。SQLServer2008将时间花在一系列其他步骤上,包括哈希匹配、并行性和其他标准内容

记住,这是同一个数据库。其中一个刚刚被复制到SQL Server 2016计算机上,并提高了其兼容性级别

为了解决这个问题,我实际上重写了存储过程,以便Sql Server 2016不会阻塞。我已经跑了250毫秒了。但是,这本来就不应该发生,我担心还有其他以前经过微调的查询或存储过程现在无法高效运行

提前谢谢

--

此外,我还建议添加traceflag-T6534以启动服务参数。这对查询时间没有影响。此外,我还尝试将选项(QUERYTRACEON 6534)添加到查询的末尾,但同样没有效果

  • 检查新服务器(DBs)与旧服务器(DBs)配置上数据/日志文件的增长情况:查询所运行的数据库+tempdb
  • 检查日志中的I/O缓冲区错误
  • 检查数据库的恢复模式-简单与完整/大容量
  • 这是一种一贯的行为吗?执行过程中可能正在运行进程
  • 关于统计数据/索引-您确定它在正确的数据样本上运行吗?(看计划)

  • 可以检查/完成更多的事情-但是在这个问题上没有足够的信息。

    从您提供的查询计划中,我发现在较新的服务器版本上没有使用空间索引。 使用空间索引提示确保查询优化器选择了具有空间索引的计划:

    select 
        [GeoServices_Location].[GeographicServicesGatewayId],
        [GeoServices_Location].[Coordinate].Lat,
        [GeoServices_Location].[Coordinate].Long
    from GeoServices_Location with (index ([spatial_index_name]))...
    
    我发现提示的问题是查询谓词中的OR操作,所以我对提示的建议在这种情况下实际上没有帮助。 然而,我看到谓词依赖于@outputControlParameter,所以重写查询以便将这两种情况分开可能会有所帮助(请参阅下面的建议)。 另外,从您的查询计划中,我看到SQL 2008上的查询计划是并行的,而SQL 2016上的查询计划是串行的。使用选项(重新编译,querytraceon 8649)强制执行并行计划(如果新的superfast服务器比旧服务器拥有更多的内核,这将有所帮助)


    嗯,如果没有看到计划或模式,很难判断……存储过程可能是SQL Server 2014中引入的新基数估计器的牺牲品。尝试在查询中使用
    选项(QUERYTRACEON 9481)
    跟踪标志。这将迫使它使用旧的估计器。如果SP正常运行,那么新的基数估计器就麻烦了。谢谢你的建议。我不知道那件事。不幸的是,这没有任何区别。这听起来很愚蠢,但是您是否检查了确保您的索引都移动到了相应的表中?偶尔迁移会遗漏一些东西。谢谢你的建议。对我甚至删除了空间索引并重新创建了它。杜桑,这是一个很好的建议。因此,当我执行此操作时,会出现以下错误:“由于此查询中定义的提示,查询处理器无法生成查询计划。”。在不指定任何提示和不使用SET-FORCEPLAN的情况下重新提交查询。“这很奇怪,但让我看到了这篇文章;这三点中没有一点涉及到这种情况,但#3很接近并描述了我们的情况。也许我们知道了什么?话虽如此,这篇文章提到的是我来自的SQL Server 2008。我还应该补充一点,添加“with(index([space\u GeoServices\u Location])”,并在SQL Server 2008上运行会导致同一个“查询处理器无法生成。。。“错误。我明白你现在的感受。我已经用新建议编辑了答案。杜桑,这有效了!它使查询立即运行。伟大的工作!我想我的问题不是我需要做些什么才能让它快速运行,而是为什么SQL Server 2016及其所有智能设备一开始就不能快速运行?换句话说,为什么SQL Server 2016选择运行串行计划而不是并行计划?更重要的是,这是SQL Server 2016中的一个缺陷吗?我庞大的数据库中还有哪些查询现在比以前运行得慢?是否存在全局SQL
    if (len(@outputControlParameter) > 0)
        select 
        [GeoServices_Location].[GeographicServicesGatewayId],
        [GeoServices_Location].[Coordinate].Lat,
        [GeoServices_Location].[Coordinate].Long
    
        from GeoServices_Location
    
        inner join GeoServices_GeographicServicesGateway
        on GeoServices_Location.GeographicServicesGatewayId = GeoServices_GeographicServicesGateway.GeographicServicesGatewayId
    
        where 
        GeoServices_Location.GeographicServicesGatewayId in (select value from #T))
        and GeoServices_GeographicServicesGateway.PrimarilyFoundOnLayerId IN(3,8,9,5) 
        option (recompile, querytraceon 8649)
    else
        select
        [GeoServices_Location].[GeographicServicesGatewayId],
        [GeoServices_Location].[Coordinate].Lat,
        [GeoServices_Location].[Coordinate].Long
    
        from GeoServices_Location with (index ([SPATIAL_GeoServices_Location]))
    
        inner join GeoServices_GeographicServicesGateway
        on GeoServices_Location.GeographicServicesGatewayId = GeoServices_GeographicServicesGateway.GeographicServicesGatewayId
    
        where 
        GeoServices_Location.Coordinate.STIntersects(@viewport) = 1
        and GeoServices_GeographicServicesGateway.PrimarilyFoundOnLayerId IN (3,8,9,5) 
        option (recompile, querytraceon 8649)