如果SQL query中有参数,SQL Server 会创建一个参数嗅探进程以提高执行性能。该计划通常是最好的并被保存以重复利用。只是偶尔,不会选择最优的执行计划而影响执行效率。

SQL Server尝试通过创建编译执行计划来优化你的存储过程的执行。通常是在第一次执行存储过程时候会生成并缓存查询执行计划。当SQL Server数据库引擎编译存储过程中侦测到有参数值传递进来的时候,会创建基于这些参数的执行计划。这种在编译存储过程中侦测参数值的方法,通常被称为“参数探测”。有时参数探测会产生效率低下的执行计划;特别是当一个存储过程调用与具有不同的基数的参数值。

什么是参数探测

探测一词就显示出了更多的不可靠性,有时候会产生好的结果就不可避免的产生一些坏的结果。参数探测是在SQL SERVER通过第一次执行时调用的参数创建的最优的执行计划。 这个第一次是指不管你执行或者是重新编译因为在缓存中没有一个现成的执行计划存在。以后使用相同的参数调用同一个存储过程的时候同样会得到一个最佳的执行方案。但是使用不同的参数的时候可能得不到最佳的方案,就是坏的结果。

并不是所有的执行计划是平等的,执行计划会按照要做什么进行一些必要的优化。SQL SERVER再去选择并确定最优的执行策略。它着眼于做什么样的查询,使用参数值来看看统计数据,做了那些计算,最终决定通过哪些步骤来解决查询。这是如何创建一个执行计划的比较简单的解释。对我们来说,重要的一点是,SQL Server通过这些参数用来确定如何处理查询。一组参数的最优执行计划可能是一个索引扫描操作,而另一组参数可能使用索引查找能更好地解决。

参数探测影响示例

假设我们有一个基于国家查询运行销售数据的存储过程:

EXEC rpt_Sales @Country ='China' - SQL Server构建针对大量销售额的国家而优化的执行计划,并且运行时间大约为750毫秒。

EXEC rpt_Sales @Country ='Monaco' - 它重用了中国的大数据缓存执行计划。这对于小国来说不是很好,但也没有那么糟糕因为只返回少量数据,所以它仍然运行在500毫秒。

现在我们重新启动SQL Server,有人首先查询Monaco:

EXEC rpt_Sales @Country ='Monaco' - SQL Server构建了一个针对微小数据量的国家而优化的执行计划,它运行时间只有50毫秒 - 比摩纳哥重用中国计划时要好很多!

EXEC rpt_Sales @Country ='China' - 它重用了Monaco的缓存计划来处理小数据。 它需要30秒,如果很多人同时运行这个存储过程,我们的服务器要开始崩溃了!

如何临时修复参数探测问题

1. 重启服务器 – 新手最先想到的解决方案,遇到问题先重启。重启服务器后会清除所有的缓存。重启完后,有人首先使用'China'去运行了rpt_Sales, 它将建立一个好的执行计划。一些初级DBA会觉得这个问题已经被修复。

2. 重启SQL Server 实例 – 随着工作经验的增长,他们意识到不能随意的重启服务器。发现重启实例也可以达到重启服务器的效果。。

3. 运行DBCC FREEPROCCACHE - 此命令会从缓存中清除所有执行计划,但不清除SQL Server的其他缓存和统计信息。相比重启来说,是个比较好的方案,因为至少可以确保数据库在线的情况下完成。

4. 重建索引 – 这其实是个意外,当SQL Server重建一个表的索引时会同时更新索引的统计信息。这也会修复了参数探测问题,因为当SQL Server意识到传入查询使用的对象的统计信息 (statistics)更新时,它将为该查询构建一个新的执行计划。

5.更新统计信息 (statistics) - 当人们学习到上述额外发现,他们意识到他们可以通过只更新统计信息数据,这是一个比重建索引容易得多的操作。

6.对一个表或存储过程运行sp_recompile - 此系统存储过程接受表或存储过程名称作为参数,并将所有相关的执行计划标记为在下次运行时强制重新编译。

7.清除特定的执行计划缓存 - 为单个查询运行DBCC FREEPROCCACHE, 只清除特定(比如rpt_Sales)的执行计划缓存。

禁用参数探测

既然参数探测会带来不确定的因素,我们可以通过使用本地变量来禁止参数探测。

比如:

create procedure rpt_Sales (@Country varchar(20))
as
begin
declare @LocCountry varchar(20)
set @LocCountry = @CustID select * from orders
where Country = @LocCountry
end

归纳总结 
参数探测(Parameter Sniffing)可以在存储过程级别上启用或禁用; 
如果检索的数据列基本上平均分布,我们不必使用本地变量(禁用Parameter Sniffing);例如,查询主键列或唯一键列(Unique Key); 
如果检索的数据列分布很大,则可以使用本地变量,禁用参数探测(Parameter Sniffing);

参数探测(Parameter Sniffing)影响存储过程执行效率解决方案的更多相关文章

  1. SQL 存储过程 执行效率优化提升 (显示估计)

    在sql server 查询区 通过执行 "显示估计的执行计划" ,可以给出 存储过程 缺少索引的提示,并自动生成建立相应 索引 的代码 显示估计的执行计划 执行结果提示: 哦,算 ...

  2. mysql存储过程的学习(mysql提高执行效率之进阶过程)

    1:存储过程: 答:存储过程是sql语句和控制语句的预编译集合,以一个名称存储并作为一个单元处理:存储过程存储在数据库内,可以由应用程序调用执行,而且允许用户声明变量以及进行流程控制,存储类型可以接受 ...

  3. 参数嗅探(Parameter Sniffing)(2/2)

    在参数嗅探(Parameter Sniffing)(1/2)里,我介绍了SQL Server里参数嗅探的基本概念和背后的问题.如你所见,当缓存的计划被SQL Server盲目重用时,会带来严重的性能问 ...

  4. 参数嗅探(Parameter Sniffing)(1/2)

    这个问题会在参数话的SQL语句(例如存储过程)与SQL Server里的计划缓存机制结合的时候会出现.这个文章分为2个部分,第1部分会介绍下参数嗅探(Parameter Sniffing)的概况,第2 ...

  5. SQL Server 并行操作优化,避免并行操作被抑制而影响SQL的执行效率

    为什么我也要说SQL Server的并行: 这几天园子里写关于SQL Server并行的文章很多,不管怎么样,都让人对并行操作有了更深刻的认识. 我想说的是:尽管并行操作可能(并不是一定)存在这样或者 ...

  6. Sql Server 带参数的存储过程执行方法

    Sql Server 带参数的存储过程执行方法 Visual C# 动态操作 SQL Server 数据库实例教程(4):带参数的存储过程执行方法 上一篇文章介绍了带参数的SQL语句执行方法和不带参数 ...

  7. 多余的Using Namespaces或引用会影响程序的执行效率么?

    在.NET程序编写中,需要using相应命名空间或添加相应的References,可有时候没有使用到的命名空间也被添加到了Using Namespaces中,那么,这样会影响程序的执行效率么? 通过示 ...

  8. 多余的Using Namespaces或引用会影响程序的执行效率么?(转)

    转自:http://www.cnblogs.com/Interkey/p/UsingNameSpace.html 多余的Using Namespaces或引用会影响程序的执行效率么? 在.NET程序编 ...

  9. 关于数据库优化2——关于表的连接顺序,和where子句的前后顺序,是否会影响到sql的执行效率问题

    有好多时候,我们常听别人说大表在前,小表在后,包括现在好多百度出来的靠前的答案都有说数据库是从右到左加载的,所以from语句最后关联的那张表会先被处理.如果三表交叉,就选择交叉表来作为基础表.等等一些 ...

随机推荐

  1. 自定义基于 VLC 的视频播放器

    前言(蛋疼的背景故事) 前段时间,接了一个小项目,有个需求是要在系统待机一段时间以后,循环播放 MV(类似于 Windows 系统的屏幕保护). 听到这个需求,我首先想到的是 MediaPlayer ...

  2. Connect() 2016 大会的主题 ---微软大法好

    文章首发于微信公众号"dotnet跨平台",欢迎关注,可以扫页面左面的二维码. 今年 Connect 大会的主题是 Big possibilities. Bold technolo ...

  3. 【翻译】MongoDB指南/CRUD操作(四)

    [原文地址]https://docs.mongodb.com/manual/ CRUD操作(四) 1 查询方案(Query Plans) MongoDB 查询优化程序处理查询并且针对给定可利用的索引选 ...

  4. ExtJS 4.2 业务开发(二)数据展示和查询

    本篇开始模拟一个船舶管理系统,提供查询.添加.修改船舶的功能,这里介绍其中的数据展示和查询功能. 目录 1. 数据展示 2. 数据查询 3. 在线演示 1. 数据展示 在这里我们将模拟一个船舶管理系统 ...

  5. video.js

    1.github地址 2.常用API: class : video-js: video-js应用视频所需的风格.js功能,比如全屏和字幕. vjs-default-skin: vjs-default- ...

  6. 前端学HTTP之实体和编码

    前面的话 每天都有各种媒体对象经由HTTP传送,如图像.文本.影片以及软件程序等.HTTP要确保它的报文被正确传送,识别.提取以及适当处理.为了实现这些目标,HTTP使用了完善的标签来描述承载内容的实 ...

  7. .net 分布式架构之分布式缓存中间件

    开源git地址: http://git.oschina.net/chejiangyi/XXF.BaseService.DistributedCache 分布式缓存中间件  方便实现缓存的分布式,集群, ...

  8. PHP获取客户端IP

    /** * 获取客户端IP */ function getClientIp() { $ip = 'unknown'; $unknown = 'unknown'; if (isset($_SERVER[ ...

  9. BPM配置故事之案例5-必填与水印文本

    物资申请表改好了,但是没过两天老李又找来了. 老李:这个表格每次都是各个部门发给我们,再由我们采购部来填,太影响效率了,以后要让他们自己填. 小明:那就让他们填呗,他们有权限啊. 老李:可是他们说不会 ...

  10. centos 6 安装配置openvpn

    下载地址:http://swupdate.openvpn.org/community/releases/http://www.oberhumer.com/opensource/lzo/download ...