本文共 1189 字,大约阅读时间需要 3 分钟。
对于服务器来说,所有查询处理都产生出执行计划是非常昂贵的开销,即使SQLServer可以在数毫秒内完成,所以SQLServer会在任何时候尽可能保留并重用计划以便全面降低开销。当执行计划被产生出来后,会存放在一个叫做计划缓存的内存块中。
当我们提交一个查询到服务器时,algebrizer过程就会创建一个hash,类似于一个对于查询的编码签名。这个hash是唯一的,昵称为查询指纹(query fingerprint)。每个查询都有一个标识,包括所有包含在查询中的文本,也包含空间及开销,优化器会对比缓存中的hash。如果查询优化器发现查询已经缓存并匹配,那么就会跳过整个优化过程并重用执行计划。
这是SQLServer其中一个强大之处,它能降低创建计划的开销。一个主要的最佳实践是编写能使得SQLServer重用计划的查询,为了确保重用,最好是使用存储过程或者参数化查询。参数化查询是在查询中由参数来识别的变量,类似于存储过程。
如果变量被硬编码,那么字符串的改变就变得很少,这将会引起与缓存中的计划不匹配,意味着会使得SQLServer找不到在缓存中的计划,然后优化过程就会触发并产生新的计划。通过查询hash并用于研究性能问题是可行的,详细内容参考DMOs章节。
SQLServer并不永久保留执行计划在内存中。它们会通过系统中的age公式(执行计划的预估开销×已经执行的次数)慢慢地aged out,比如执行计划的预估开销是10,并且已经执行了5次,那么age就是50。一个叫做lazywriter的内部进程,用于释放所有类型的缓存(包括计划缓存),会周期性地扫描缓存中的对象并每次降低一个age值。
如果同时下面的条件满足,计划就会被移除出内存:
l 系统需要更多的内存。
l 计划的age值达到0。
l 该计划没有被当前的连接所引用。
执行计划并不是神圣不可侵犯的。某些事件和动作会引发计划被重编译。记住一个重要的事情,重编译执行计划是一个非常耗时的操作。下面的动作将导致一个执行计划发生重编译:
l 查询所引用的表的结构或者架构发生改变。
l 查询所使用的索引变更了。
l 查询所使用的索引被删除。
l 查询所使用的统计信息被更新了。
l 调用了函数sp_recompile。
l 查询所引用的表中键由于大数据量的插入或删除而引起统计信息的改变。
l 对于触发器,inserted或者deleted表有明显的增加。
l 在一个单查询中混合使用了DDL和DML,通常叫做延迟编译。
l 在查询执行过程中SET选项的改变。
l 查询所使用的临时表的架构或结构发生了改变。
l 查询所使用的动态视图发生改变。
l 查询所使用的游标选项发生改变。
l 改变远程行集,如在一个分布式分区视图中。
l 当使用客户端游标,如果FORBROWSE选项改变,也会引发重编译。
转载地址:http://uajoo.baihongyu.com/