sqLSERVER 计划缓存
在这一期的性能调优培训里,我想详细谈下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 计划缓存的更多相关文章
- SQLServer中的执行计划缓存由于长时间缓存对性能造成的干扰
本文出处:http://www.cnblogs.com/wy123/p/7190785.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错 ...
- RECONFIGURE语句会清空计划缓存么?
几个星期前,有个网友问我一个非常有趣的问题:RECONFIGURE语句会清空计划缓存么?通常我对这个问题的答案是简单的是,但慢慢的我找出了真正的答案是“看情况啦”.我们来看下它,为什么“它看情况”. ...
- 谈一谈SQL Server中的执行计划缓存(下)
简介 在上篇文章中我们谈到了查询优化器和执行计划缓存的关系,以及其二者之间的冲突.本篇文章中,我们会主要阐述执行计划缓存常见的问题以及一些解决办法. 将执行缓存考虑在内时的流程 上篇文章中提到了查询优 ...
- 谈一谈SQL Server中的执行计划缓存(上)
简介 我们平时所写的SQL语句本质只是获取数据的逻辑,而不是获取数据的物理路径.当我们写的SQL语句传到SQL Server的时候,查询分析器会将语句依次进行解析(Parse).绑定(Bind).查询 ...
- 如何用参数化SQL语句污染你的计划缓存
你的SQL语句的参数化总是个好想法.使用参数化SQL语句你不会污染你的计划缓存——错!!!在这篇文章里我想向你展示下用参数化SQL语句就可以污染你的计划缓存,这是非常简单的! ADO.NET-AddW ...
- [译]SQL Server 之 查询计划缓存和重编译
查询优化是一个复杂而且耗时的操作,所以SQL Server需要重用现有的查询计划.查询计划的缓存和重用在多数情况下是有益的的,但是在某些特殊的情况下,重编译一个查询计划可能能够改善性能. SELECT ...
- 查看SQLServer各种缓存的情况
查看页面缓存: SELECT * FROM sys.dm_os_buffer_descriptors 清除页面缓存: CHECKPOINTDBCC DROPCLEANBUFFERS 查看执行计划缓存: ...
- sqlserver清除缓存(转载)
sqlserver清除缓存,记录查询时间 1 2 3 4 5 6 7 8 9 10 11 12 --1. 将当前数据库的全部脏页写入磁盘.“脏页”是已输入缓存区高速缓存且已修改但尚未写入磁盘的数据 ...
- 浅析SQL Server中的执行计划缓存(上)
简介 我们平时所写的SQL语句本质只是获取数据的逻辑,而不是获取数据的物理路径.当我们写的SQL语句传到SQL Server的时候,查询分析器会将语句依次进行解析(Parse).绑定(Bind).查询 ...
随机推荐
- boost 部分编译
完整编译boost库需要很长时间,而且我们不一定会用到所有的库. 那么如何只编译只需要的库呢? 解压boost源码,进入解压后的目录 ./bootstrap.sh生成bjam ./bjam --bui ...
- HDU - 6041:I Curse Myself(Tarjan求环&K路归并)
There is a connected undirected graph with weights on its edges. It is guaranteed that each edge app ...
- Java JDK安装和配置(Windows)
安装和配置JDK JDK中自带了JRE,不需要单独下载, 打开JDK安装, 选择安装目录,下一步,装完JDK,会问是否安装JRE,选下一步, 最后还会问是否安装Java FX, 装完后就全部完成了JD ...
- LeetCode Next Closest Time
原题链接在这里:https://leetcode.com/problems/next-closest-time/description/ 题目: Given a time represented in ...
- LA4728 Squares
题意 PDF 分析 就是求凸包点集的直径. 当然选择旋转卡壳. 然后是实现上的技巧: 当Area(p[u], p[u+1], p[v+1]) <= Area(p[u], p[u+1], p[v] ...
- 系列文章--SQLite文章
SQLite 随机取n行的方法 SQLite多线程写锁文件解决方案 sqlite和sql server语法上的一些区别 sqlite编程插入标示字段,获得新id C# SQLiteHe ...
- FastAdmin 学习线路 (2018-09-09 增加 Layer 组件)
FastAdmin 学习线路 (2018-09-09 增加 Layer 组件) 基础 HTML CSS DIV Javascript 基础 jQuery php 基础 对象 命名空间 Apache 或 ...
- Linux bash shell 入门
https://www.cnblogs.com/cosiray/archive/2012/03/02/2377099.html
- sql server中类似oracle中decode功能的函数
sqlserver 2008 写法 select t.PROJECTNAME, t.BUILDCONTENTSCALE, CASE t.PROJECTLEVEL ' THEN '国家重点' ' THE ...
- SQL2005 如何在没有日志文件的情况下如何恢复MDF数据库文件?
第一步:先建立一个同名数据库,停止SQL SERVER2005,将没有日志的的.mdf数据库文件覆盖刚新建的.mdf数据库文件,重新启动数据库. 第二步:在查询分析器中运行如下代码(将数据库名修改为您 ...