Microsoft SQL Server 2016 调用 1000 次的存储过程性能下降

acg*_*acg 4 performance sql-server stored-procedures sql-server-2016 query-performance

语境 :

小表,存储过程更新表,前两千命中没问题。在第一次点击后,它开始以蜗牛般的速度爬行。此存储过程在我们当前使用调用 C# 应用程序的 SQL Server 2008 R2 环境中没有问题。在我们针对 SQL Server 2016 的新测试环境中,我们看到了这个问题。查询的违规部分处理了一个 where 子句,它对不等于小表更新的参数的列进行了四次比较:

WHERE A.Column1 <> @param1 OR A.Column2 <> @param2     etc..
Run Code Online (Sandbox Code Playgroud)

我的假设是参数嗅探,但已经通过各种查询提示排除了这一点。

我也试过:

  • 更改为选择不更新
  • 玩并行度 (MAXDOP)
  • 更新统计信息并重新编译,甚至在中间进行
  • 索引的各种变化
  • X 次迭代后在调用 C# 代码时重置连接池
  • 删除任何交易控制

似乎可以解决问题的唯一更改是删除 where 子句并将逻辑推送到 setter:

SET A.Column1 = CASE 
        WHEN A.Column1 <> @param1
            THEN @param1
        ELSE A.Column1
        END
Run Code Online (Sandbox Code Playgroud)

我不喜欢更改代码,但我在网上找不到其他资源可以回答为什么 SQL Server 2016 会崩溃。

任何帮助,将不胜感激。

Kin*_*hah 5

在 SQL Server 2014 及更高版本中,引入了新的基数估计逻辑。

来自 BOL :

基数估计逻辑(称为基数估计器)在 SQL Server 2014 中重新设计,以提高查询计划的质量,从而提高查询性能。新的基数估计器结合了适用于现代 OLTP 和数据仓库工作负载的假设和算法。它基于对现代工作负载的深入基数估计研究,以及我们在过去 15 年改进 SQL Server 基数估计器的经验。来自客户的反馈表明,虽然大多数查询将从更改中受益或保持不变,但与之前的基数估计器相比,少数查询可能会出现回归

最近,我们从 SQL Server 2012 升级到 SQL Server 2014 并受到新基数估计器的影响 - 查询超时,cpu 挂钩接近 100%。

经过多次故障排除、更新统计信息、重建索引、进行查询计划分析,我们发现将兼容级别更改为 sql 2012 效果很好。

Paul White 解释 -多个谓词的基数估计

如果数据库兼容性级别设置为低于 120,或者如果跟踪标志 9481 处于活动状态,则 SQL Server 2014 中的选择性计算的行为与以前的版本相同(跟踪标志 4137 的工作方式与以前相同)。

所以我的建议是

  • 对于揭示问题的少量查询,请使用 QUERYTRACEON(9481) 提示。
  • 如果您不想赌博,那么只需将跟踪标志TF9481作为启动参数,这样它就会在服务器重新启动期间保持不变。

注意:启用后TF 9481,您无需将数据库的兼容级别设置为较低级别。

来自KB2801413

9481:在使用默认数据库兼容级别 120 运行 SQL Server 2014 时使用。跟踪标志 9481 强制查询优化器在创建查询计划时使用基数估计器的版本 70(SQL Server 2012 版本)。

作为旁注,除了适当的测试之外,您还想查看TF4199(将其视为打开查询优化器的每个修复程序的主键)。TF4199 行为随 sql server 2016 发生变化。. TF4199 对我的环境有很大帮助,并且默认情况下对所有新安装都启用。

在 SQL Server 2016 中,您不需要打开跟踪标志9481

SELECT  name, value  
    FROM  sys.database_scoped_configurations  
    WHERE name = 'LEGACY_CARDINALITY_ESTIMATION'; 
-- if above is having value = 0, then set to ON
ALTER DATABASE
    SCOPED CONFIGURATION  
        SET LEGACY_CARDINALITY_ESTIMATION = ON;  
go  
Run Code Online (Sandbox Code Playgroud)

对于 Trace Flag 4199,你可以做

ALTER DATABASE
    SCOPED CONFIGURATION  
        SET QUERY_OPTIMIZER_HOTFIXES = ON
Run Code Online (Sandbox Code Playgroud)