在这一期的性能调优培训里,我想详细谈下SQL Server里计划缓存及其副作用。在上一周你已经学到,每个提交给SQL Server的逻辑查询会编译成物理执行计划。那个执行计划然后会被缓存,即被称为计划缓存,用作后期的重用。首先我们来看下即席SQL语句(adhoc SQL statements,对应的反义词:prepared SQL statements)的副作用,即带来的性能问题。

即席SQL语句(adhoc SQL statements)

每次当你提交一个即席SQL语句到SQL Server时,对每个唯一的查询,都会有执行计划被编译。“唯一的查询”是什么意思?答案很简单:SQL Server对完整的SQL语句(包括可能硬编码的参数值)生成一个hash值,并使用这个hash值作为在计划缓存里查找值。如果找到这个值的执行计划,这个计划就会被重用,否则的话新的计划会被编译并最后在计划缓存里缓存。看下我们提交下面这3个查询给SQL Server:

 1 SELECT * FROM Sales.SalesOrderHeader
2
3 WHERE CustomerID = 11000
4
5 GO
6
7 SELECT * FROM Sales.SalesOrderHeader
8
9 WHERE CustomerID = 30052
10
11 GO
12
13 SELECT * FROM Sales.SalesOrderHeader
14
15 WHERE CustomerID = 11223
16
17 GO

对这3个查询,SQL Server会编译3个不同的执行计划,因为你提供硬编码的参数值。因此计算出来的hash值在3个查询之间是不同的,找不到被缓存的计划。作为一个副作用,对于几乎相同的查询,你有3个执行计划。这个问题被称为计划缓存污染(Plan Cache Pollution)

你用不同的执行计划污染了你的计划缓存,这些计划是不能被重用的(因为硬编码的参数值),并且你在浪费大量有用的内存,这些内存在SQL Server里可以被其他组件使用。缓存的目的应该是持续数次的高重用,特定SQL语句不属于这个情况。

计划稳定性

如果你参数话你的SQL语句,或者使用存储过程。在那个情况下,SQL Server可以非常容易的重用执行计划。但是即使重用执行计划也会带来性能的问题。比如SQL Server为一个查询编译了一个需要执行书签查找的执行计划,因为用到的非聚集索引没有覆盖到查询字段。

在第8周我们说过,如果你从表获取少量数据,书签查找还是有用的。当你越过临界点时,使用全表/索引扫描将更高效。但是SQL Server如果重用缓存的执行计划,就不会考虑这个选择了——SQL Server只会盲目的重用你的计划——即使性能非常糟糕!我们看看下面的实际执行计划:

这里SQL Server盲目重用了包含书签查找的被缓存的计划。如你所见,估计行数(estimated number of rows  )和实际行数(actual number of rows )完全不同。SQL Server基于假设那个查询只返回1条记录来编译和缓存了计划。但是实际上SQL Server返回了1499条记录。看看执行计划,我们会更清晰,优化器是假设只返回1条记录才执行这个操作的。

这会导致你没有计划稳定性。基于估计行数,你得到书签查找的缓存计划,要不就是如果越过临界点的话是全表/索引扫描。这个是我们在性能调优时经常碰到的性能问题。

sqLSERVER 计划缓存的更多相关文章

  1. SQLServer中的执行计划缓存由于长时间缓存对性能造成的干扰

    本文出处:http://www.cnblogs.com/wy123/p/7190785.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错 ...

  2. RECONFIGURE语句会清空计划缓存么?

    几个星期前,有个网友问我一个非常有趣的问题:RECONFIGURE语句会清空计划缓存么?通常我对这个问题的答案是简单的是,但慢慢的我找出了真正的答案是“看情况啦”.我们来看下它,为什么“它看情况”. ...

  3. 谈一谈SQL Server中的执行计划缓存(下)

    简介 在上篇文章中我们谈到了查询优化器和执行计划缓存的关系,以及其二者之间的冲突.本篇文章中,我们会主要阐述执行计划缓存常见的问题以及一些解决办法. 将执行缓存考虑在内时的流程 上篇文章中提到了查询优 ...

  4. 谈一谈SQL Server中的执行计划缓存(上)

    简介 我们平时所写的SQL语句本质只是获取数据的逻辑,而不是获取数据的物理路径.当我们写的SQL语句传到SQL Server的时候,查询分析器会将语句依次进行解析(Parse).绑定(Bind).查询 ...

  5. 如何用参数化SQL语句污染你的计划缓存

    你的SQL语句的参数化总是个好想法.使用参数化SQL语句你不会污染你的计划缓存——错!!!在这篇文章里我想向你展示下用参数化SQL语句就可以污染你的计划缓存,这是非常简单的! ADO.NET-AddW ...

  6. [译]SQL Server 之 查询计划缓存和重编译

    查询优化是一个复杂而且耗时的操作,所以SQL Server需要重用现有的查询计划.查询计划的缓存和重用在多数情况下是有益的的,但是在某些特殊的情况下,重编译一个查询计划可能能够改善性能. SELECT ...

  7. 查看SQLServer各种缓存的情况

    查看页面缓存: SELECT * FROM sys.dm_os_buffer_descriptors 清除页面缓存: CHECKPOINTDBCC DROPCLEANBUFFERS 查看执行计划缓存: ...

  8. sqlserver清除缓存(转载)

    sqlserver清除缓存,记录查询时间   1 2 3 4 5 6 7 8 9 10 11 12 --1. 将当前数据库的全部脏页写入磁盘.“脏页”是已输入缓存区高速缓存且已修改但尚未写入磁盘的数据 ...

  9. 浅析SQL Server中的执行计划缓存(上)

    简介 我们平时所写的SQL语句本质只是获取数据的逻辑,而不是获取数据的物理路径.当我们写的SQL语句传到SQL Server的时候,查询分析器会将语句依次进行解析(Parse).绑定(Bind).查询 ...

随机推荐

  1. I.MX6 Android 5.1 纯Linux、U-Boot编译

    /***************************************************************************** * I.MX6 Android 5.1 纯 ...

  2. EMQ (Erlang/Enterprise/Elastic MQTT Broker)

    EMQ (Erlang/Enterprise/Elastic MQTT Broker) https://www.cnblogs.com/SteveLee/p/9843215.html MQ介绍 EMQ ...

  3. hibernate的list和iterate的区别

    一.先介绍一下java中的缓存系统JCS(java cache system)  1.JCS(Java Caching System)是一个对象Cache,它可以把Java对象缓存起来,提高那些访问频 ...

  4. fn project 试用之后的几个问题

    今天试用fnproject  之后自己有些思考,后面继续解决   1. 目前测试是强依赖 dockerhub 的,实际可能不是很方便 2. 如何与k8s .mesos.docker swarm  集成 ...

  5. 6 字典和集合——《Swift3.0从入门到出家》

    字典和集合 字典 字典是集合类型存放多个键值对,其中键是唯一的,不能重复 字典中存放的键值对是无序的,写入的顺序和读取的顺序可能不同 字典中存放的数据是任意类型 字典可以分为可变字典和不可变字典 创建 ...

  6. android栈和队列

    android栈和队列 栈和队列是两种特殊的线性表,它们的逻辑结构和线性表相同,只是其运算规则较线性表有更多的限制,故又称它们为运算受限的线性表.LinkedList数据结构是一种双向的链式结构,每一 ...

  7. jquery中ajax异步调用接口

    之前写过一个原始的.无封装的页面,没有引入任何外部js,直接实例化Ajax的XmlRequest对象去异步调用接口,参见Ajax异步调用http接口后刷新页面,可对比一下. 现在我们用jquery包装 ...

  8. Voting and Shuffling to Optimize Atomic Operations

    2iSome years ago I started work on my first CUDA implementation of the Multiparticle Collision Dynam ...

  9. TPS和QPS区别

    TPS和QPS区别 http://blog.csdn.net/kobejayandy/article/details/9374747

  10. rbenv配置

    git clone https://github.com/rbenv/rbenv.git ~/.rbenv # 用来编译安装 ruby git clone git://github.com/sstep ...