sqlserver兼容性级别和基数估计(代码片段)

薛定谔的DBA 薛定谔的DBA     2023-02-14     709

关键词:

从 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

 

基数估计算法简介(代码片段)

基数估计算法简介注1:本文是之前工作时在团队内分享的一个PPT的文字版本.注2:我有了新的个人博客地址下文中的sqrt表示开根号(sqrt(4)=2),m^n表示m的n次方什么是基数(Cardinality)基数指的是一个可重复集合中不重复元素的个... 查看详情

16周翻译(代码片段)

第三章 统计 SQLServer查询优化器在为查询选择执行计划时使用基于成本的模型。它估计不同执行计划的成本,并选择成本最低的一个。但是,请记住,SQLServer并不搜索可用于查询的最佳执行计划,因为评估所有可能的替代... 查看详情

数据库的快照隔离级别(snapshotisolation)(代码片段)

...3.html隔离级别定义事务处理数据读取操作的隔离程度,在SQLServer中,隔离级别只会影响读操作申请的共享锁(SharedLock),而不会影响写操作申请的互斥锁(ExclusiveLock),隔离级别控制读操作的行为:在读数据时是否使用共享锁... 查看详情

sqlserver中的事务与事务隔离级别以及如何理解脏读,未提交读,不可重复读和幻读产生的过程和原因(代码片段)

...的事务控制过程的,但是发现很多基本的概念还是需要有SQLServer事务和事务的隔离级别做基础铺垫。所以花了点时间,把SQLServer数据库中的事务概念,ACID原则,事务中常见的问题,问题造成的原因和事务隔离级别等这些方面的... 查看详情

SQL Server 2014 兼容级别错误

】SQLServer2014兼容级别错误【英文标题】:SQLServer2014wrongcompatibilitylevel【发布时间】:2019-10-0813:54:57【问题描述】:我正在使用SQLServer2014ManagementStudio,我认为它的兼容性级别为110,但在尝试使用PERCENT_RANK()函数时,出现错误\'PERCE... 查看详情

redishyperloglog(代码片段)

...edis在2.8.9版本添加了HyperLogLog结构。RedisHyperLogLog是用来做基数统计的算法,HyperLogLog的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。在Redis里面,每个HyperLogL... 查看详情

数据结构和算法(十七)排序算法之基数排序(代码片段)

1、基数排序介绍基数排序(radixsort)属于“分配式排序”(distributionsort),又称为“桶子法”(bucketsort),或者binsort,它通过把要排序的元素分配到一些桶中,进行排序。基数排序属于稳定的排序&#... 查看详情

算法计数排序桶排序和基数排序详解(代码片段)

01.计数排序、桶排序与基数排序并不是所有的排序都是基于比较的,计数排序和基数排序就不是。基于比较排序的排序方法,其复杂度无法突破(nlogn)的下限,但是计数排序桶排序和基数排序是分布排序,他们是可以突破这个下限... 查看详情

更改sql2005数据库的兼容级别对数据库有影响吗

...。参考技术A兼容级别主要体现在语法上的差异。例如,SQLServer2000(80)可以使用*=和=*,这种语法在SQLServer2005(90)就会报错,应使用OUTERJOIN关键字。其次,兼容级别体现在功能的差异,例如,兼容级别在SQLServer2012(110),才可... 查看详情

constraintlayout,子视图的提升和向后兼容性(代码片段)

我有一个ConstraintLayout和一个Button和一个ImageView作为其孩子的意见。ImageView被放置在Button上,期望ImageView将被吸引到Button上。(当然,我可以用Button添加图像作为drawabl。但是,在我的场景中,我想用按钮宽度做一些动画,我希望I... 查看详情

数据结构-排序之基数排序(使用java代码实现)(代码片段)

前言最近在学习数据结构的排序算法时,学到了基数排序。对于基数排序的算法的具体实现过程有了一定了解,但在具体实现的时候出现了一些小问题。在和同学讨论和查阅资料过后打算使用java代码将其实现出来。基数... 查看详情

sqlserver的四个事务隔离级别到底怎么理解?(代码片段)

一:背景1.讲故事在有关SQLSERVER的各种参考资料中,经常会看到如下四种事务隔离级别。READUNCOMMITTEDREADCOMMITTEDSERIALIZABLEREPEATABLEREAD随之而来的是大量的文字解释,还会附带各种脏读,幻读,不可重复读常常会把初学者弄得晕头转向... 查看详情

数据结构学习笔记——基数排序和排序算法总结(代码片段)

...、排序思想二、算法分析三、排序算法总结一、排序思想基数排序与前面的排序算法不一样,它不基于比较和移动元素来进行排序,而是基于多关键字排序的思想,将一个逻辑关键字分为多个关键字,它是基于关... 查看详情

ssrs报告在加载ie11时陷入困境(代码片段)

我们正在运行SQLServer2008R2。所有这些报告都运行正常,直到我们将IE从10升级到11.每次我们运行报告时,它都会永远停留在加载状态。尝试将文档模式更改为其他版本。答案根据OP,将站点添加到兼容性视图。浏览器检测也可能需... 查看详情

基数排序法(代码片段)

【1】基数排序以前研究的各种排序算法,都是通过比较数据大小的方法对欲排数据序列进行排序整理过程。而基数排序却不再相同,那么,基数排序是采用怎样的策略进行排序的呢?简略概述:基数排序是通... 查看详情

排序算法下——桶排序计数排序和基数排序(代码片段)

桶排序、计数排序和基数排序这三种算法的时间复杂度都为$O(n)$,因此,它们也被叫作线性排序(LinearSort)。之所以能做到线性,是因为这三个算法是非基于比较的排序算法,都不涉及元素之间的比较操作。1.桶排序(BucketSort... 查看详情

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

】在PostgreSQL中显示基数估计错误的示例查询【英文标题】:SampleQuerytoshowCardinalityestimationerrorinPostgreSQL【发布时间】:2014-09-2001:19:09【问题描述】:我正在开发一个使用PostgreSQL9.3的项目。我使用下面的查询来展示选择性估计错误... 查看详情

基本算法-基数排序(代码片段)

...业转载请注明出处前言    本文介绍一种排序算法——基数排序,是经典排序算法之一。以下是本篇文章正文内容,包括算法简介、算法特点、算法实现和C++示例。一、基数排序简介    基数排序不需要进行元... 查看详情