存储过程重编译的优点、缺点、确定引发语句

存储过程通过明确地将查询的可变部分转换为参数来增进执行计划的可重用性。这使执行计划在查询以可变部分的相同或不同值重新提交时可以被重用。存储过程包含一组复杂的SQL语句,使生成存储过程的执行计划的代价有些高。因此,通常重用存储过程的执行计划来代替生成新计划是有利的。但是,有时候现有的计划可能不适用或者在重用期间可能不能提供最佳的处理策略。SQL Server重编译存储过程中的语句来生成一个新的执行计划,以解决这个问题。

一、重编译的好处

  存储过程的重编译既有好处又有缺点,有时候,为查询考虑一个新的处理策略而不是重用现有计划可能更经济。特别是表(或对应的统计)中数据的分布变化或者表中添加了新的索引时。SQL Server 2008中的重编译在语句级别上。语句级重编译降低开销是因为只重编译单独的语句,而不是存储过程中的所有语句。而在SQL Server 2005以前重编译方法导致存储过程一次又一次地被完全重编译。

  创建一个存储过程并执行,代码如下:

CREATE PROC dbo.getPerson
AS
SELECT Id,Name,Age FROM PersonHunderThousand
WHERE Name = ‘夏娩好‘

EXEC dbo.getPerson

  目前执行当前存储过程的执行计划如下:

  

  假如我们建了一个覆盖索引之后:

CREATE NONCLUSTERED INDEX IX_Name ON PersonHunderThousand(Name) INCLUDE(Age)

  明显,再次执行该查询,使用索引的执行计划更有利:

  

  SQL Server自动重编译了存储过程以有效使用索引。

  在这种情况下,花费额外的CPU周期重新编译存储过程建立更好的执行计划是有利的。

  SQL Server自动侦测需要重新编译现有计划的条件。SQL Server根据特定的规则确定现有计划需要重新编译的时机。如果存储过程的一个特定实现进入重编译规则的范围(执行计划老化、SET选项变化等),则存储过程将在每次符合重编译要求时重新编译,SQL Server可能不能生成更好的执行计划。

二、重编译存储过程的缺点

  在SQL Server Profiler中,SP_Recompile事件用于跟踪语句重编译。也可以使用SQL:StmtRecompile事件,这是存储过程事件。

  上面创建的索引是有益于存储过程里面的语句的,这次我们先删除刚刚创建的覆盖索引,然后换成一个对查询语句里无益的索引:

EXEC dbo.getPerson
GO
CREATE NONCLUSTERED INDEX IX_Name ON PersonHunderThousand(InCome)
GO
EXEC dbo.getPerson

  我们来看SQL Server Profiler监控的输出:

  

  我们看到,重新编译对该存储过程无益。但是不幸地,它进入了导致SQL Server在每次执行时重新编译存储过程的条件范围。这使存储过程缓冲效率降低,并且将CPU周期浪费在重新生成相同的计划上。因此,知道导致存储过程重新编译的条件,并且在实现存储过程时用一切办法避免这些条件是很重要的。当然,这个例子有点牵强,谁没事会一天到晚建索引啊。

三、确认导致重编译的语句

  SQL Server可以重新编译存储过程中的单条语句或整个存储过程。因而,为了找到重编译的起因,确认不能重用现有计划的SQL语句是很重要的。

  可以使用Profiler工具来跟踪存储过程重编译。也可以使用Profiler工具来确认导致存储过程重编译的语句。

  分析存储过程重编译的事件和数据列:

事件 数据列
SP:Completed EventClass
SP:Recompile TextData
SP:Starting EventSubClass
SP:StmtCompleted(可选) SPID
SP:StmtStaring(可选) StartTime

  考虑下面简单的存储过程:

CREATE PROC dbo.InsertPerson
AS
CREATE TABLE t1(c1 INT)
INSERT INTO t1(
c1
)VALUES(42);    --数据修改导致重编译

  输出如下:

  

  从输出可以看到,有一个重编译事件(SP:Recompile),表示该存储过程经受了重编译。当存储过程第一次执行时,SQL Server编译存储过程并生成一个执行计划。

  执行计划值维持在易失性的内存中,它们在SQL Server重启时被抛弃。在服务器重启后的存储过程下一次执行时,SQL Server再次编译存储过程并且生成执行计划。这些编译不被看做存储过程的重编译,因为该计划不存在于缓冲中用于重用,SP:Recompile事件表示计划已经存在但是不能被重用。为了了解那条语句引起的重编译,需要查看SP:Recompile事件中的TextData列,它明确地说明被重编译的语句。还可以使用SP:StmtStarting事件和重编译事件的组合来确认导致重编译的存储过程语句。SP:Recompile事件紧接在SP:StmtStarting事件之后发生表明该存储过程语句导致重编译。使用TextData列更简单,但是在非常复杂的过程中,使用SP:StmtStarting事件可能更有意义。

  注意,在存储过程重编译之后,导致重编译的存储过程语句再次启动以执行新的计划。可以使用SP:StmtStarting事件或SP:StmtCompleted事件以确认导致重编译的存储过程语句。

时间: 2024-12-15 07:10:14

存储过程重编译的优点、缺点、确定引发语句的相关文章

SQL SERVER 临时表导致存储过程重编译(recompile)的一些探讨

SQLSERVER为了确保返回正确的值,或者处于性能上的顾虑,有意不重用缓存在内存里的执行计划,而重新编译执行计划的这种行为,被称为重编译(recompile).那么引发存储过程重编译的条件有哪一些呢?下面罗列了一些导致重编译(recompile)的条件:     - 对查询所引用的表或视图进行更改(ALTER TABLE 和 ALTER VIEW).     - 对执行计划所使用的任何索引进行更改.     - 对执行计划所使用的统计信息进行更新,这些更新可能是从语句(如 UPDATE STA

分析存储过程重编译的起因以及避免

为了改进性能,分析重编译的起因很重要.往往,重编译可能并不需要,可以避免它以改进性能.了解导致重编译发生的不同条件有助于评估重编译的起因,并决定在重编译不必要时避免它的方法. 存储过程重编译在以下情况下发生: 存储过程语句中引用的常规表.临时表或视图的架构变化.架构变化包括表的元数据或表上索引的变化: 常规或临时表的列上的绑定(如默认/规则)变化. 表索引或列上的统计的变化超过一定的阈值. 存储过程编译时一个对象不存在,但是在执行期间创建(延迟对象解析): SET选项变化: 执行计划老化并释放:

关于T-SQL重编译那点事,WITH RECOMPILE和OPTION(RECOMPILE)区别仅仅是存储过程级重编译和SQL语句级重编译吗

本文出处:http://www.cnblogs.com/wy123/p/6262800.html   在考虑重编译T-SQL(或者存储过程)的时候,有两种方式可以实现强制重编译(前提是忽略导致重编译的其他因素的情况下,比如重建索引,更新统计信息等等), 一是基于WITH RECOMPILE的存储过程级别重编译,另外一种是基于OPTION(RECOMPILE)的语句级重编译. 之前了解的比较浅,仅仅认为是前者就是编译整个存储过程中的所有的语句,后者是重编译存储过程中的某一个语句,也没有追究到底是不

WITH RECOMPILE和OPTION(RECOMPILE)区别仅仅是存储过程级重编译和SQL语句级重编译

在考虑重编译T-SQL(或者存储过程)的时候,有两种方式可以实现强制重编译(前提是忽略导致重编译的其他因素的情况下,比如重建索引,更新统计信息等等), 一是基于WITH RECOMPILE的存储过程级别重编译,另外一种是基于OPTION(RECOMPILE)的语句级重编译. 之前了解的比较浅,仅仅认为是前者就是编译整个存储过程中的所有的语句,后者是重编译存储过程中的某一个语句,也没有追究到底是不是仅仅只有这么一点区别. 事实上在某些特定情况下,两者的区别并非仅仅是存储过程级重编译和语句级重编译的

如何track存储过程的编译次数

原文:如何track存储过程的编译次数 转载自此处 有个script我们很熟悉,是用来去查找当前SQL Server中哪些存储过程变重编译的次数最多的: --Gives you the top 25 stored procedures that have been recompiled. select top 25 sql_text.text, sql_handle, plan_generation_num,  execution_count, dbid,  objectid into DMV_

win10 + VS2010 + OpenCV2.4.10重编译OpenCV开发环境搭建

win10 + VS2010 + OpenCV2.4.10重编译OpenCV开发环境搭建 重编译的优点:能够调试的时候看OpenCV的源码. 重编译要得到的东西:Debug版本号和Release版本号的dll,lib,头文件.(dll加入到环境变量里,执行时用,自己编译的dll调试时能够跟踪到Opencv的源代码内:lib和头文件配置到编译器里) PS:假设仅仅是使用Opencv而不须要跟踪源代码,则使用Opencv自带的库文件就可以. 跳到5配置Opencv开发环境.相应的文件都在..\ope

sqlserver 存储过程中使用临时表到底会不会导致重编译

曾经在网络上看到过,SqlServer的存储过程中使用临时表,会导致执行计划无法重用, 运行时候会导致重编译的这么一个说法,自己私底下去做测试的时候,根据profile的跟踪结果, 如果不是统计信息变更导致导致的重编译,单单是使用临时表,并不会导致重编译, 但是对于一些特殊的情况,又确实会出现重编译的, 为了弄清楚这个问题,查阅了大量的资料,才把这个问题弄清楚,这里特意记录下来,希望武断地认为存储过程中使用了临时表就会导致重编译的这个观点得到纠正. 首先进行下面的测试,我们知道,导致临时表重编译

存储过程中引用的常规表,临时表以及表变量是否会导致存储过程的重编译

在存储过程中,经常要引用一些表来存储一些中间数据,用完即删.对于这个中间表,用常规表,临时表或者表变量有什么区别呢? 下面我们看一下这三种中间表是否会造成执行计划的重编译. 首先打开sql server profile,监控存储过程. 1.建第一个存储过程,在存储过程中创建常规表TT1 CREATE PROCEDURE TEST1_PRO AS BEGIN CREATE TABLE TT1( ID INT IDENTITY, NAME VARCHAR(10) ) INSERT INTO TT1

SQLSERVER编译与重编译

SQLSERVER编译与重编译 编译的含义 当SQLSERVER收到任何一个指令,包括查询(query).批处理(batch).存储过程.触发器(trigger) .预编译指令(prepared statement)和动态SQL语句(dynamic SQL Statement)要完成语法解释.语句解释, 然后再进行“编译(compile)”,生成能够运行的“执行计划(execution plan)”.在编译的过程中, SQLSERVER会根据所涉及的对象的架构(schema).统计信息以及指令的