SQL 编译与重编译

编译的含义

 

当SQLSERVER收到任何一个指令,包括查询(query)、批处理(batch)、存储过程、触发器(trigger)

 

、预编译指令(prepared statement)和动态SQL语句(dynamic SQL Statement)要完成语法解释、语句解释,

 

然后再进行“编译(compile)”,生成能够运行的“执行计划(execution plan)”。在编译的过程中,

 

SQLSERVER会根据所涉及的对象的架构(schema)、统计信息以及指令的具体内容,估算可能的执行计划,

 

以及他们的成本(cost),最后选择一个SQLSERVER认为成本最低的执行计划来执行。执行计划生成之后,

 

SQLSERVER通常会把他们缓存在内存里,术语统称他们叫“plan cache”以后同样的语句执行,SQLSERVER就可以使用同样的执行计划,而无须再做一次编译。

 

这种行为叫“重用(reuse)或者叫重用执行计划”。但是有时候,哪怕是一模一样的语句,SQL下次执行还是要再做一次编译。

 

这种行为叫“重编译(recompile)”。执行计划的编译和重编译都是要消耗资源的。

 

如果执行计划能够重用,那么SQLSERVER就不需要再执行上面的过程,加快执行指令的速度.

 

重编译的发生场景

 


 

但是有些时候,SQLSERVER为了确保返回正确的值,或者有性能上的顾虑,有意不重用缓存在内存里的执行计划,而现场编译一份。

 

这种行为,被称为重编译(recompile)。下面是比较常见的会发生重编译的情形:

 

 

 

1、当指令或者批处理所涉及的任何一个对象(表格或者视图)发生了架构(schema)变化

 

例如,在表或者视图上添加或删除了一个字段,添加或者删除了一个索引,在表上添加或者删除了一个约束条件(constraints)等。

 

定义发生了变化,原来的执行计划就不一定正确了,当然要重编译

 

 

 

2运行过sp_recompile

 

当用户在某个存储过程或者触发器上运行过sp_recompile后,下一次运行他们就会发生一次重编译。

 

如果用户在某个表或者视图上运行了sp_recompile,那么所有引用到这张表(或者视图)的存储过程在下一次运行前,都要做重编译

 

 

 

3、有些动作会清除内存里的所有执行计划,迫使大家都要做重编译

 

例如,下列动作会清除整个SQLSERVER服务器缓存的所有执行计划:

 

(1)Detach一个数据库

 

(2)对数据库做了升级,在新的服务器上,会发生执行计划清空

 

(3)运行了DBCC freeproccache

 

(4)运行了reconfigure语句

 

(5)运行了alter database..collate语句修改了某个数据库的字符集(collation)

 

 

 

下列动作会清除SQLSERVER服务器缓存的某个数据库的执行计划:

 

DBCC FLUSHPROCINDB

 

清除SQL Server 2000服务器内存中的某个数据库的存储过程缓存内容

 

1 DECLARE @a INT
2 SELECT @a=DB_ID('gposdb')
3 DBCC flushprocindb(@a)

 

ALTER DATABASE ...MODIFY NAME语句

 

ALTER DATABASE ...SET ONLINE语句

 

ALTER DATABASE...SET OFFLINE语句

 

ALTER DATABASE...SET EMERGENCY语句

 

DROP DATABASE 语句

 

当一个数据库自动关闭时

 

DBCC CHECKDB语句结束时

 

 

 

4、当下面这些SET 开关值变化后,先前的那些执行计划都不能重用

 

ansi_null_dflt_off,

 

ansi_null_dflt_on,

 

ansi_nulls,

 

_ansi_padding

 

ansi_warnings,

 

arithabort,

 

concat_null_yields_null,

 

datefirst,dateformat,

 

forceplan,

 

language,

 

no_browsetable,

 

numeric_roundabort,

 

quoted_identifier

 

这是因为这些SET开关会影响语句的执行的行为,甚至带来不同的结果。他们发生变化了,SQLSERVER就要根据新的设置重做执行计划

 

往往存储过程使用一段时间就会出现查询慢的情况,可以使用重编译或者删除重建的方法处理。

1 Create procedure usp_test 
2 @a INT
3 WITH RECOMPILE 
4 
5    
6     as 
7     
8     SELECT 1

原文出自 http://www.cnblogs.com/lyhabc/archive/2013/01/17/2865290.html

 

posted @ 2015-10-23 10:19  ぃ流年☆  阅读(4121)  评论(0编辑  收藏  举报