当 Sql Server 收到任何一个指令,包括:查询、批处理、存储过程、触发器、预编译指令和动态SQL Server语句,要完成语法解析、语义分析,然后再进行"编译",生成能够运行的"执行计划"。在编译的过程中,SQL Server 会根据所涉及的对象的架构、统计信息,以及指令的具体内容,估算可能的执行计划,以及它们的成本,最后选择一个SQL Server认为成本最低的语句。
执行计划生成之后,SQL Server 通常会把它们缓存到内存里,术语统称它们叫“Plane Cache”。以后同样的语句执行,SQL Server就可以使用同样的执行计划,而无须再做一次编译。这种行为,叫做“重用”。但是有时候,哪怕是一模一样的语句,SQL Server 下次执行还是要再做一次编译。这种行为叫“重编译”。执行计划的编译和重编译都是要耗费资源的。
执行计划的好坏当然决定了语句的执行速度。对于同样一条语句,使用好的执行计划可能会比差的要快几百倍,甚至几千倍。所以从这一角度上来讲,没运行一条语 句,都把它先编译一遍当然是最好的。它能够保证使用的执行计划是 SQL Server 能找到的最优的。但是 SQL Server 每秒钟可能会运行成百上千的指令。如果每个都编译一遍,是资源的严重浪费。所以 SQL Server 在这里也试图寻找一个平衡点,使用优先的 complie/recomplie,得到最好的 整体性能。
查看 SQL Server 缓存的执行计划,可以运行下面这条语句:Select*From Sys.syscacheobjects
对不同的指令调用方法, SQL Server 做执行计划缓存和重用机制也有所不同。下面介绍最常见的几种:
1. Adhoc 语句
一组包含 Select、Insert、Update、Delete 的批处理指令。对这样的指令,只有前后完全一直,包括字母的大小写、空格、回车换行都一致, SQL Server 才认为是两条一样的语句,才能够重用执行计划。所以这个要求还是挺高的。
2. 用 Exec() 的方式运行动态 SQL Server 语句
有些应用程序为了开发上的灵活程度,在程序运行过程中,动态地拼接成一个语句字符串,然后用 Exec() 的方式执行。这种调用方法被称为“dynamic SQL”。它的好处就是很灵活,可以根据客户的选择,动态生成指令,而不仅限于预定义的那几种。但是它的缺点也是太灵活了,客户发过来的语句每次都不一 样,或者语句主体部分是一样的,但是参数不一样, SQL Server 都要做编译。这点和 adhoc 语句是一样的。
3. 自动参数化查询
对于一些比较简单的查询, SQL Server 2005 自己就可以做自动参数化,把语句里的参数用一个变量代替,但是这仅限于很简单的查询。
4. 用 sp_executesql 的方式调用的指令
查询自动参数化在很多种条件下是不支持的,而且它还是要为每句查询生成一个 adhoc 的执行计划。所以它并不是减少比哪一的最有手段。改用 sp_executesql 能够更有效地增加执行计划重用。
5. 存储过程
对用户经常要调用的指令,把他们做成存储过程,既方便管理、规范脚本,又能够大大提高执行计划调用,是值得推荐的一种做法。从 SQL Server 的角度,最好绝大多数指令都能够以存储过程的方式调用,尽量少使用 Dynamic SQL 的方式。
例如,在表或者视图上添加或删除另一个字段、添加或删除了一个索引,在表上添加或者删除了一个约束条件等。定义发生了变化,原来的执行计划就不一定正确了,当然要重编译。
2. 运行过 sp_recomplie 后
当用户在某个存储过程或者触发器上运行过 sp_recomplie 后,下一次运行它们就会发生一次重编译。如果用户在某个表或试图上运行了 sp_recomplie ,那么所有引用到这张表或视图的存储过程在下一次运行前,都要做重编译
- Detach 一个数据库
- 对数据库做了一个升级,在新的服务器上会发生执行计划清空
- 运行了 DBCC FreeProccache 语句
- 运行了 ReConfigure 语句
- 运行了 Alter DataBase ... Modify FileGroup 语句
- 用 Alter DataBase ... Collate 语句修改了某个数据库的字符集
- DBCC FlushProcinDB 语句
- Alter DataBase ... Modify Name 语句
- Alter DataBase ... Set Online 语句
- Alter DataBase ... Set Offline 语句
- Alter DataBase ... Set EmerGency 语句
- Drop DataBase 语句
- 当一个数据库自动关闭时
- DBCC CheckDB 语句结束时
4. 当一些 Set 开关值变化后,先前的那些执行计划都不能重用
5. 当表格或试图上的统计信息发生变化后
当统计信息被手动跟新后,或者 SQL Server 发现某个统计信息需要自动更新时, SQL Server 会对所涉及的语句都做重编译。
3. 将 数据库 Parameterization 属性设置成 Forced
5. Create Procedure ... with Recompile 选项 和 Exce ... with Recomplie 选项
7. 用户在调用语句的时候,使用了 "Keep Plan" 或者 "KeepFixed Plan" 这样的查询提示
1678445897QQQQQQ
1678141447QQQQQQ
1668913194QQQQQQ
不知道博主交换链接否,谢谢