SQL Server 兼容性级别和基数估计

Posted 薛定谔的DBA

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL Server 兼容性级别和基数估计相关的知识,希望对你有一定的参考价值。

从 1998 年到 2014 年初,SQL Server 使用了一个基数估计器 (CE),但会在 SQL Server 的每个版本中引入数据库兼容级别(SQL Server 2008 R2 除外)。SQL Server 的兼容级别与 SQL Server 版本对应如下。

SQL Server 版本兼容级别
SQL  Server 7.070
SQL  Server 200080
SQL  Server 200590
SQL  Server 2008100
SQL Server 2008 R2
SQL  Server 2012110
SQL  Server 2014120
SQL  Server 2016130
SQL  Server 2017140
SQL  Server 2019150

在 SQL Server 7.0 和 SQL Server 2012 之间,数据库的兼容性级别与该数据库中查询将使用的基数估计器之间没有联系。这是因为只有一个基数估计器,但它在 1998 年进行了重大更新。数据库的兼容性级别仅用于向后功能兼容、以及启用/禁用每个新版本 SQL Server 中的一些新功能。较低的兼容性级别允许你继续使用不再受支持的语法,有时它会阻止你使用新的语法结构。与 SQL Server 数据库的版本不同,你可以随时使用简单的 ALTER DATABASE 命令将数据库的兼容级别更改为任何受支持的兼容级别。

默认情况下,如果你在 SQL Server 2012 中创建了一个新数据库,兼容性级别将设置为 110,但你可以根据需要将其更改为更早的级别。如果你恢复了从 SQL Server 2008 实例到 SQL Server 2012 实例的数据库备份,它会升级数据库的文件版本,但会保留它在 SQL Server 2008 实例上的兼容性级别(需满足 SQL Server 2012 支持的最低兼容版本)。除了了解数据库的文件版本和数据库的兼容性级别之间的根本区别之外,在 SQL Server 2014 发布之前,大多数 DBA 和开发人员不必太担心数据库的兼容性级别。在许多情况下,大多数数据库在迁移到 SQL Server 的新版本后从未更改其兼容性级别。这通常不会导致任何问题,除非你确实需要在最新的数据库兼容性级别中使用新功能。

SQL Server 2014 变更

随着 SQL Server 2014 的发布,这种旧的情况发生了根本性的变化。SQL Server 2014 引入了一个“新”基数估计器,当数据库处于 120 兼容级别时,它默认启用。在经典白皮书中,“Optimizing Your Query Plans with the SQL Server 2014 Cardinality Estimator” 解释了这一变化的背景和行为。在许多情况下,使用新的基数估计器时,你的大多数查询运行得更快,但使用新的基数估计器时遇到一些性能回归的查询也是相当常见的。如果发生这种情况,SQL Server 2014 没有那么多选项来缓解由新 CE 引起的性能问题。白皮书详细介绍了这些选项,但基本上,你只能使用实例级跟踪标志或查询级查询提示来控制查询优化器使用哪个基数估计器,除非你想恢复到 110 或更低的兼容性级别.

《Optimizing Your Query Plans with the SQL Server 2014 Cardinality Estimator

https://docs.microsoft.com/en-us/previous-versions/dn673537(v=msdn.10)?redirectedfrom=MSDN

SQL Server 2016 变更

SQL Server 2016 引入了数据库作用域配置选项,通过使用 ALTER DATABASE SCOPED CONFIGURATION 命令,可以控制实例级的配置。在 SQL Server 2016 中,这些选项包括 MAXDOP、LEGACY_CARDINALITY ESTIMATION、 PARAMETER_SNIFFING、QUERY_OPTIMIZER_HOTFIXES。还有一个CLEAR PROCEDURE_CACHE 选项,允许你清除单个数据库的所有计划缓存。

在此上下文中最相关的是 LEGACY_CARDINALITY ESTIMATION 和 QUERY_OPTIMIZER_HOTFIXES 数据库范围的配置选项。


LEGACY_CARDINALITY ESTIMATION 启用遗留的CE,不管数据库兼容性级别怎么设置。这相当于跟踪标志 9481,但它只影响所涉及的数据库而不是整个实例。它允许你将数据库兼容性级别设置为130,以获得许多功能和性能优势,但仍然可在数据库范围使用遗留的 CE (除非查询级别中使用查询提示覆盖)。

QUERY_OPTIMIZER_HOTFIXES 选项相当于数据库级别的跟踪标志 4199。当你使用130数据库兼容性级别(不启用跟踪标志4199)时,SQL Server 2016 将在SQL Server 2016 RTM 之前启用所有查询优化器热修复。如果你启用跟踪标志4199或启用QUERY_OPTIMIZER_HOTFIXES,你也会得到所有在SQL Server 2016 RTM 之后发布的查询优化器热修复。

SQL Server 2016 SP1还引入了 USE HINT 查询提示,它比旧的 QUERYTRACEON 查询提示更易于使用、理解和记忆。这使你能够更细粒度地控制数据库兼容性级别与基数估计器版本相关的优化器行为。可以使用查询sys.dm_exec_valid_use_hints 获取正在运行的 SQL Server 的有效 USE HINT 列表。

SQL Server 2017 变更

在SQL Server 2017 中添加了新的自适应查询处理特性,当你使用数据库兼容性级别140时,默认情况下启用。

微软正试图摆脱“新CE”和“旧CE”的旧术语,因为在每个SQL Server 的新版本中,查询优化实际上都有更改和修复。正因为如此,再也没有单一的“新CE”了。相反,微软想要参考CE70(默认CE为SQL Server 7.0到SQL Server 2012), CE120为SQL Server 2014, CE130为SQL Server 2016, CE140为SQL Server 2017,以及CE150为SQL Server 2019。从SQL Server 2017 CU10开始,你可以使用USE HINT 功能来控制查询提示。例如:

/*...query...*/ OPTION (USE HINT('QUERY_OPTIMIZER_COMPATIBILITY_LEVEL_130'));

这是一个查询提示,用于对指定的查询强制CE130进行基数估计。

SQL Server 2019 变更

SQL Server 2019 将增加更多的性能提升和行为变化,当数据库使用兼容性模式150时,默认启用这些功能。一个主要的例子是标量UDF内联。另一个例子是智能查询处理特性,它是SQL Server 2017中自适应查询处理的超集。

有五个新的 USE HINT 选项,包括禁用批处理模式或禁用自适应内存授予反馈的方法,如下所示:

DISABLE_BATCH_MODE_ADAPTIVE_JOINSDISABLE_BATCH_MODE_MEMORY_GRANT_FEEDBACKDISABLE_INTERLEAVED_EXECUTION_TVFDISALLOW_BATCH_MODEQUERY_OPTIMIZER_COMPATIBILITY_LEVEL_150

还有16个新的数据库范围的配置选项(从CTP 2.2开始),使你能够在数据库级控制更多的选项,这些选项也受跟踪标志或数据库兼容性级别的影响。它使你能够更细粒度地控制在默认情况下启用的数据库兼容性级别为150的高级更改。如下所示:

总结

迁移到SQL Server 2016或更高版本比迁移到旧版本的SQL Server要复杂得多。主要是各种数据库兼容性级别和各种基数估计器版本相关的更改。

微软推荐的升级流程是升级到最新的SQL Server版本,但保持原数据库兼容性级别。然后在每个数据库上启用查询存储,并收集工作负载上的基线数据。接下来再将数据库兼容性级别设置为最新版本,然后使用查询存储通过强制执行最后一个好执行计划来修复性能问题。

在对数据库进行升级迁移时,为了避免可能存在的性能问题,需要将数据库兼容性级别更改为适当的版本、使用适当的数据库范围配置选项、适当查询提示…这些都是非常重要的。

基数估计 (SQL Server)

https://docs.microsoft.com/zh-cn/sql/relational-databases/performance/cardinality-estimation-sql-server

 

以上是关于SQL Server 兼容性级别和基数估计的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 兼容性级别和基数估计

SQL Server中关于基数估计如何计算预估行数的一些探讨

SQL Server中关于基数估计如何计算预估行数的一些探讨

基数估计算法简介

DSE精选综述 | 关于提升数据库优化器:基数估计代价模型计划枚举

在 PostgreSQL 中显示基数估计错误的示例查询