在前阵子写的一篇博文“SQL SERVER 2014 下IF EXITS 居然引起执行计划变更的案例分享”里介绍了数据库从SQL SERVER 2005升级到 SQL SERVER 2014后,发现一个SQL出现性能问题,当时分析后发现执行计划变了,导致SQL出现了性能问题。但是没有彻底搞清楚为什么出现这种情况。当时看到Actual Number of Rows 与Estimated Number of Rows之间的偏差较大(统计信息是最新的),以为是优化器的Bug造成的。其实罪魁祸首是SQL SERVER 2014新特性——基数评估(Cardinality Estimator)所引起的。IF EXISTS完全成了我这个标题党的替罪羊(罪过罪过)。下面我再就这个问题展开做一次分析。

查看该SQL语句的实际执行计划,在属性里面我们可以看到CardinalityEstimationModelVersion的值为120,120表示这是新的基数评估,70就是老的基数评估

其实当数据库的兼容级别为120的时候,默认使用新的基数评估。也就是说启用了新的基数评估,那么我们现在使用查询跟踪标记9481来关闭新的基数评估,使用老的基数评估。

DBCC TRACEON(9481, 1);

 

GO

启用跟踪标记9481后,这个SQL语句的执行计划变了(可以对比图4),可以看到CardinalityEstimationModelVersion的值也变为了70。SQL语句一秒就执行完了。这个是因为基数评估出现了偏差导致了不合适的JOIN算法。

我们对比下面”图四:旧执行计划“,发现其实还是使用Nested Loops,只是外部循环表与内部循环表变了。

图四:旧执行计划

那么关于新的基数评估(Cardinality Estimator)特性,你想多了解一些这方面的知识,可以参考官方文档Optimizing Your Query Plans with the SQL Server 2014 Cardinality Estimator。 中文翻译版本可以参考SQL Server 2014新特性——基数评估(白皮书阅读笔记)。下面是官方文档关于基数评估出现偏差可能会造成的一些后果:

对于基数评估,每个执行计划中的运算符都有评估值输入,这个值决定了优化器使用什么算法的操作符,同时也决定了最终的执行计划。所以如果评估出现偏差,会导致执行计划选择出现偏差,导致无法选出一个高效的执行计划。

评估出现偏差会出现以下结果:

如果评估过小:

1.原本可以使用并行计划更加有效的,现在使用串行计划

2.不合适的join算法

3.不合适的索引选择,和索引访问方法

如果评估过大:

1.原本使用串行计划更加有效,现在使用并行计划

2.不合适的join算法

3.不合适的索引选择,和索引访问方法

4.过多的内存分配

5.内存浪费和没必要的并发

上面这段对应的英文资料如下所示(英语原文作参考,这才是原汁原味的信息):

The individual operator cost models receive the estimates as input. The estimates are a major factor in deciding which physical operator algorithms and plan shapes (such as join orders) are chosen. They also determine the final query plan that executes. Given these critical plan choices, when the cardinality estimation process contains a significantly skewed assumption, this can lead to an inefficient plan choice. This can, in turn, result in degraded performance.

Under estimating rows can lead to memory spills to disk, for example, where not enough memory was requested for sort or hash operations. Under estimating rows can also result in:

  1. The selection of serial plan when parallelism would have been more optimal.
  2. Inappropriate join strategies.
  3. Inefficient index selection and navigation strategies.

Inversely, over estimating rows can lead to:

  1. Selection of a parallel plan when a serial plan might be more optimal.
  2. Inappropriate join strategy selection.
  3. Inefficient index navigation strategies (scan versus seek).
  4. Inflated memory grants.
  5. Wasted memory and unnecessarily throttled concurrency.

Improving the accuracy of row estimates can improve the quality of the query execution plan and, as a result, improve the performance of the query.

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

其实关于SQL SERVER 2014这个新的基数评估(Cardinality Estimator)特性,确实造成了不少SQL出现性能问题。我们数据库升级到SQL SERVER 2014后,被这个新特性坑惨了,由于没有选择最优的执行计划,导致一些SQL出现严重的性能问题,也间接导致了SQL之间的阻塞(block)急剧上升。开发人员和我都在救火队员的角色中疲于奔命。最后我不得不采取将数据库的兼容基本从120降为110。从而立马解决了这个问题。另外从我搜索的一些资料看,SQL SERVER 2014这个新的基数评估(Cardinality Estimator)这个新特性确实还有很多不完善的地方。因为也有不少人都发现升级到SQL Server 2014后出现了性能问题。例如:

MS SQL Server CPU load goes up dramatically when turning on 2014 features by setting compatibility level

Query is slow in SQL Server 2014, fast in SQL Server 2012

 

参考资料:

http://dba.stackexchange.com/questions/95609/sql-server-performance-is-slow-when-migrated-from-sql-server-2012-to-sql-server

http://www.cnblogs.com/Amaranthus/p/3678647.html

小心SQL SERVER 2014新特性——基数评估引起一些性能问题的更多相关文章

  1. SQL Server 2014新特性——基数评估(白皮书阅读笔记)

    基数评估 目录 基数评估 说明 基数评估准确的重要性 模型假设 启用新的基数评估 验证基数评估的版本 在迁移到新的基数评估前要测试 校验基数评估 偏差问题 需要手动处理的变化 避免因为新的CE造成性能 ...

  2. SQL Server 2014 新特性——内存数据库

    SQL Server 2014 新特性——内存数据库 目录 SQL Server 2014 新特性——内存数据库 简介: 设计目的和原因: 专业名词 In-Memory OLTP不同之处 内存优化表 ...

  3. 谈谈我的微软特约稿:《SQL Server 2014 新特性:IO资源调控》

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 撰写经历(Experience) 特约稿正文(Content-body) 第一部分:生活中资源 ...

  4. SQL Server 2014新特性——Buffer Pool扩展

    Buffer Pool扩展 Buffer Pool扩展是buffer pool 和非易失的SSD硬盘做连接.以SSD硬盘的特点来提高随机读性能. 缓冲池扩展优点 SQL Server读以随机读为主,S ...

  5. SQL Server 2014 新特性:IO资源调控

    谈谈我的微软特约稿:<SQL Server 2014 新特性:IO资源调控> 2014-07-01 10:19 by 听风吹雨, 570 阅读, 16 评论, 收藏, 收藏 一.本文所涉及 ...

  6. SQL Server 2014新特性:五个关键点带你了解Excel下的Data Explorer

    SQL Server 2014新特性:五个关键点带你了解Excel下的Data Explorer Data Explorer是即将发布的SQL Server 2014里的一个新特性,借助这个特性讲使企 ...

  7. SQL Server 2014 新特性——内存数据库(转载)

    目录 SQL Server 2014 新特性——内存数据库 简介: 设计目的和原因: 专业名词 In-Memory OLTP不同之处 内存优化表 内存优化表的索引 并发能力的提升 和竞争对手相比几点 ...

  8. [SQL Server 2014] SQL Server 2014新特性探秘

    SQL Server 2014新特性探秘(1)-内存数据库   简介 SQL Server 2014提供了众多激动人心的新功能,但其中我想最让人期待的特性之一就要算内存数据库了.去年我再西雅图参加SQ ...

  9. SQL Server 2014新特性:其他

    AlwaysOn 增强功能 SQL Server 2014 包含针对 AlwaysOn 故障转移群集实例和 AlwaysOn 可用性组的以下增强功能: “添加 Azure 副本向导”简化了用于 Alw ...

随机推荐

  1. 关于客户端接口分页sql语句

    今天突然翻到为客户端写分页数据的sql,发现其实逻辑不对.列表是按照id降序的 当时这样写的: #翻上一页: select 字段 from 表 where id>lastId order by ...

  2. 实现iOS图片等资源文件的热更新化(三):动态的资源文件夹

    简介 此文,将尝试动态从某个不确定的文件夹中加载资源文件.文章,会继续完善自定义的 imageNamed 函数,并为下一篇文章铺垫. 这么做的意义 正如我们经常所说的那样,大多数情景知道做事的意义往往 ...

  3. The Practice of .NET Cross-Platforms

    0x01 Preface This post is mainly to share the technologies on my practice about the .NET Cross-Platf ...

  4. C#中 @ 的3种用途

    1.忽略转义字符例如string fileName = "D:\\文本文件\\text.txt";使用@后string fileName = @"D:\文本文件\text ...

  5. 【WCF】WCF中的InstanceContext与ConcurrencyMode【转】

    一.前言 最近忙于公司的在线升级项目,一个人要负责公司四大产品的在线升级,这四个产品是在Revit中以插件形式存在的,目前基于WCF来实现.等客户总量突破5万了,再重新用socket实现. 由于有服务 ...

  6. authorization与URL授权

    利用Web.config中的authorization标签设置授权属于URL授权. 使用 URL 授权 通过 URL 授权,您可以显式允许或拒绝某个用户名或角色对特定目录的访问权限.为此,请在该目录的 ...

  7. mybatis中的查询缓存

    一: 查询缓存 Mybatis提供查询缓存,用于减轻数据压力,提高数据库压力. Mybatis提供一级缓存和二级缓存. 在操作数据库时需要构造SqlSession对象,在对象中有一个数据结构(Hash ...

  8. 【夯实PHP系列】购物车代码说明PHP的匿名函数

    1. 定义:匿名函数(Anonymous functions),也叫闭包函数(closures),允许 临时创建一个没有指定名称的函数.最经常用作回调函数(callback)参数的值.当然,也有其它应 ...

  9. ABP之动态WebAPI(二)

    HttpControllerDescriptor与HttpActionDescriptor HttpControllerDescriptor封装了某个HttpController类型的元数据,我们可以 ...

  10. JS效果集锦

    秒后消失 $('.success_message').text( '反馈成功' );    setTimeout(function(){         $( ".success_messa ...