存储过程包含一组复杂的SQL语句,使生成存储过程的执行计划的代价有些高。因此通常重用存储过程的执行计划来代替生成新计划是有利的。但是有时候现有的计划可能不适用或者在重用期间可能不能提供最佳的处理策略。SQL Server重编译存储过程中的语句来生成一个新的执行计划以解决这个问题。

1、产生存储过程重新编译的要素   为提高SQL性能,不仅仅是只注意SQL语句写法问题,也不仅是意味者提高硬件要求,我们也必须要关注存储过程编译的时机,以及影响存储过程重新编译的起因,也是改进性能的一项不可避免的因素。
   影响存储过程重新编译因素:
  a、存储过程语句中引用常规表、临时表或视图架构变化(索引修改、创建……)
  b、表索引或列上统计变化超过一定的阈值
  c、存储过程编译时一个对象不存在,但是在执行期间创建
  d、执行计划老化并释放
  e、表列上绑定值变化
  f、 环境变化(Set)
  g、参数的不确定性

2、表列上绑定值的变化
  表结构如下:创建一张表并设置DateTimes默认值为当前时间 ,创建存储过程信息如下

  修改Test表中DateTimes绑定值信息,并执行,使用SQL Profiler工具查看存储过程执行的信息(进行了重新编译)

3、存储过程语句中引用常规表、临时表或视图架构变化(索引修改、创建……)  当存储过程中的临时表……架构等发生变化也会导致存储过程重新编译。当我们修改了表架构时,原有的执行计划引擎将会被SQL放弃,当执行这个存储过程时,SQL Server会自动检测架构是否修改并重新编译。

4、表索引或列上统计变化超过一定的阈值  Sqlserver 查询是基于开销查询的,在首次生成执行计划时是基于多阶段的分析优化才确定出较好的执行计划。而这些开销的基数估计,是根据统计信息来确定的。统计信息其实就是对表的各个字段的总体数据进行分段分布数据库默认都会自动维护。如何查看表的统计信息(展开表->选择统计信息->右键属性)
  当统计数超过阈值是就会引起存储过程重新编译,(BUT)但是重新编译可以生成一个与之前完成想同的执行计划这样,重新编译的开销就是额外的开销应当避免;如何避免不必要编译这里提供两种方法(未重新编译):
  1、保持原有的执行计划方案(keepfixedPlan)
  2、关闭表自动统计信息(sp_autostats)

5、执行计划老化并释放  SQL Server通过维护缓冲中执行计划的寿命来管理存储过程缓冲的大小,如果一个存储过程长时间未被重新执行,执行计划的寿命字段将下降为0,内存短缺时将把该计划从缓冲中删除。当这种情况发生并且存储过程被重新执行时,将生成一个新计划并将其缓冲到过程缓冲中,如果系统中有足够的内存,未使用的计划在内存压力增加之前不会被删除。
  查询缓存执行计划方式:
  Sys.dm_exec_cached_plans:    包含缓存的执行计划,每个执行计划对应一行。
  Sys.dm_exec_plan_attributes: 这是一个系统函数,每一个执行计划都对应着一些属性,在这个系统函数中包含着这些属性。
  Sys.dm_exec_sql_text:             这是一个系统函数,返回文字格式的执行计划。
  Sys.dm_exec_query_plan:        这是一个系统函数,返回xml格式的执行计划。
  删除缓存方式:
  清除全局缓存使用下面的语句: 
  DBCC DROPCLEANBUFFERS;
  从全局缓存中清除执行计划,使用下面的语句: 
  DBCC FREEPROCCACHE;
  清除某一个数据库中的执行计划,使用下面的语句: 
  DBCC FLUSHPROCINDB(<db_id>);
  清除一个特定的执行计划使用下面的语句: 
  DBCC FREESYSTEMCACHE(<cachestore>);

6、环境变化(Set)  所谓环境变化指的是SQL SERVER ManageMent Studio开发环境设置的变化

7、参数的不确定性  参数不确定性就很简单了,在不少的存储过程中都会编写部分的业务逻辑信息,进行SQL拼接操作,但是不正当的拼接就会降低存储过程的性能,导致执行存储过程执行时执行计划中多出一步重新编译操作从而降低了存储过程的性能(案例见:高效安全式SQL拼接)

8、重新编译执行时机

学习了影响存储过程重新编译因素后,有不少开发人员会问我们什么时候该让存储过程进行编译什么时候又不该让其编译换句话来说,重新编译应在什么时候执行??
   a、当使用表(或对应的统计)中数据的分布变化或者表中添加了新的索引时。这时为查询计划生成了一个策略提高了查询性能时需重新编译不要使用缓存计划;
   b、当删除一个对查询性能没有任何影响的索引时,这时对此查询没有任何影响时就不需要重新译否则降低了缓冲效率添加了CPU额外的开销

9、操作存储过程编译的方式  a、调用sp_recompile系统存储过程(exec sp_recompile 'Test')对指定的表每次使用时进行编译


  b、使用WITH RECOMPILE子句(强制数据库引擎每次重新生成执行计划,针对特定的存储过程、或某一个比较特殊的存储执行才会使用;使用With Recompile 生成的计划不会被缓存,也不会影响到原缓存的计划),


  c、使用OPTIMIZE FOR查询提示(RECOMPILE方式提供了完全不使用计划缓存的节奏。但有些时候特性谓语的执行计划被使用的次数很多,仅仅那些谓语条件产生大量返回结果集的参数编译,我们可以考虑Optimize For参数)


  使用了该参数会使得缓存的执行计划按照OPTIMIZE FOR后面的谓语条件来生成并缓存执行计划,这也可能造成不在该参数中的查询效率低下,但是该参数是我们选择的,因此通常我们知道哪些谓语条件会被使用的多一些。

转载于:https://www.cnblogs.com/tx720/p/5965930.html

导致存储过程重新编译的原因相关推荐

  1. java编译sql存过_SQL SERVER 临时表导致存储过程重编译(recompile)的一些探讨

    SQLSERVER为了确保返回正确的值,或者处于性能上的顾虑,有意不重用缓存在内存里的执行计划,而重新编译执行计划的这种行为,被称为重编译(recompile).那么引发存储过程重编译的条件有哪一些呢 ...

  2. mysql 存储过程 compile_SQLSERVER临时表导致存储过程重编译(recompile)的一些探讨_MySQL...

    SQLSERVER为了确保返回正确的值,或者处于性能上的顾虑,有意不重用缓存在内存里的执行计划,而重新编译执行计划的这种行为,被称为重编译(recompile).那么引发存储过程重编译的条件有哪一些呢 ...

  3. Oracle 存储过程 无法编译 解决方法(转载)

    声明:本文为转载,如果有侵犯知识版本,请通知本人,本人将即刻停止侵权行为: http://blog.csdn.net/tianlesoftware/article/details/7412555 Or ...

  4. codeblock的c语言编译,CodeBlocks无法编译的原因和解决办法

    原标题:CodeBlocks无法编译的原因和解决办法 CodeBlocks16.01最新版百度云下载(安装包内含编译器) https://pan.baidu.com/s/1kWjtmKJ CodeBl ...

  5. 对PInvoke函数函数调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。...

    C#引入外部非托管类库时,有时候会出现"对PInvoke函数调用导致堆栈不对称.原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配"的报错. 通常在DllImport标 ...

  6. 调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配

     调用导致堆栈不对称.原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配.请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配 用c#调用视频接口相关的dll,dll ...

  7. dma访问主存时_DMA导致Cache数据一致性问题的原因及其解决方式(理论篇)

    点击上方公众号名称关注,获得更多内容 ✎ 编 者 悟 语 唉!嫉妒之心真的能俘获它所接触到的任何目标啊--"欲加之罪,何患无辞"呢?"觉悟高的"更有" ...

  8. oracle protocol=beq 不可用,学习笔记:Oracle数据库坏块 深入研究obj$坏块导致exp/expdp不能执行原因...

    天萃荷净 深入研究Oracle坏块obj$导致exp/expdp不能执行导出的原因 上篇(案例:Oracle出现obj$坏块exp/expdp导出不能导出的解决办法ORA-01578 ORA-0111 ...

  9. java的stackoverflow_call stack - 导致java.lang.StackOverflow的原因

    实际上导致java.lang.StackOverflowError的原因通常是无意的递归. 对我来说,通常我打算为覆盖方法调用超级方法. 比如在这种情况下: publicclassVehicle{pu ...

最新文章

  1. java计算筛子概率_剑指Offer解题报告(Java版)——n个骰子的点数 43
  2. linux时间戳截止,给定一个Unix时间戳,如何得到那一天的开始和结束?
  3. Java并行有优势吗_Java中不同的并发实现的性能比较
  4. docker中部署mysql
  5. 超细粒度分析XLNet中神奇的Attention Mask
  6. JavaOne 2015:为JDK 9做准备– blog @ CodeFX
  7. Java中的变量数据类型补充
  8. 10a 16a 插座区别_电动汽车小知识(NO·5):电动汽车能否用家里的插座进行充电?...
  9. C语言,使用结构体读入两个在同一年的日期,判断日期是否合法,并计算两个日期之间相差的天数。结构体定义如下:...
  10. BTC:关键阻力的突破会带来持续的积极情绪
  11. 2022 Android 进阶学习RoadMap
  12. python回归算法预测数据_python逻辑回归算法预测
  13. php 网站攻击,php网站主要攻击方式
  14. Linux:进程(二)
  15. php dingo和jwt,DingoApi 中使用 JWT
  16. Linux下套接字详解(七)----线程池accept处理高并发connect
  17. 如何用计算机学唱歌,男孩学唱歌教程 男生如何练习唱歌?
  18. Elasticsearch如何创建索引,添加,删除,更新文档
  19. 国际快递 什么是国际快递物流
  20. 淘宝/天猫获取sku详细信息 API 返回值说明

热门文章

  1. python3.5安装教程及环境配置_Windows7环境下Python2.7与Python3.5共存安装
  2. jni java参数签名,什么是“方法签名”参数调用使用JNI的Java方法?
  3. 登录账号用户名判断_如何设计 QQ、微信等第三方账号登陆 ?
  4. JAVA中dot的用法_Java 方法
  5. python网络通信中cs架构_python3基于TCP实现CS架构文件传输
  6. linux进程map,linux内存优化一文中 查看进程mem_map 的实现
  7. java中replaceall用法_Java中String的ReplaceAll使用小结
  8. python的zip_python中的zip()函数
  9. linux 内核dump,linux内核调试技巧之一 dump_stack【转】
  10. 电子电路分析与设计:数字电子技术_红外气体传感器电子电路设计