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

系统 1425 0
原文: 如何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_Top25_Recompile_Commands

from sys.dm_exec_query_stats a

    cross apply sys.dm_exec_sql_text(sql_handle) as sql_text

where plan_generation_num >1

order by plan_generation_num desc

go

 

那么,这个脚本究竟是记录什么情况下的存储过程 recomile 呢?

 

我们在 SQL Server 上创建一个这样的 store procedure

 

create proc aaa

as

select plan_generation_num,* FROM DMV_Top25_Recompile_Commands where plan_generation_num  > 2

 

然后准备好用这个脚本来返回 plan_generation_num 的值

select top 25 sql_text.text, sql_handle, plan_generation_num,  execution_count,

    dbid,  objectid

from sys.dm_exec_query_stats a

    cross apply sys.dm_exec_sql_text(sql_handle) as sql_text

where  sql_text.text like '%aaa%'

order by plan_generation_num desc

 

 

Exec aaa 之后的脚本返回结果:

 

这里的第六行结果集就是我们的存储过程 aaa 。这时的 plan_generation_num 值显示为 1.

 

接下来我们 mark recompile

sp_recompile aaa

然后再次执行   exec aaa

 

使用脚本查询:

 

 

这里看到存储过程重编译以后, plan_generation_num 的值并没有增加。

那为什么我们还会使用这样的脚本来返回重编译次数很多的存储过程呢?

 

接下来我们再次将存储过程 mark  recompile ,然后直接使用脚本查询:

这时,我们发现该存储过程的 plan  text 已经从 DMV 中移除了。看起来 sp_recompile 会直接将 cache 中缓存的执行计划和语句直接标识成不可用。因此 DMV 中就没有相关的记录了。

这就是说,存储过程标识重编译这种模式导致的重编译,从 DMV 里面是没有办法跟踪的。

 

那么从性能监视器的计数器   sp recompilation/sec ”里面能不能跟踪到呢?

我们反复执行:

sp_recompile aaa

exec aaa

 

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

性能监视器中一直显示为 0

 

那么 plan_generation_num 的值究竟是什么含义呢? BOL 中的解释很简单:

A sequence number that can be used to distinguish between instances of plans after a recompile.

中文版的含义为:可用于在重新编译后区分不同计划实例的序列号。

 

这里并没有说明如何去计算的序列号。我们从另一篇英文的 blog 中找到了更加详细的说明:

There are a lot of interesting columns in P and S, especially in S, and here I will only discuss what I have learned about plan_generation_num in S. SQL Server 2005 treats the compiled plan for a stored procedure as an array of subplans, one for each query statement. If an individual subplan needs recompilation, it does so without causing the whole plan to recompile. In doing so, SQL Server increments the plan_generation_num on the subplan record to be 1 + MAX(plan_generation_num for all subplans). The general distribution of plan_generation_num among all subplans for a given plan is such that it has multiple of 1's and distinct numbers > 1. That is because all subplans start with 1 as their plan_generation_num. Appendix A is the query for learning plan_generation_num.

 

http://lfsean.blogspot.com/2008/02/understanding-sql-plangenerationnum.html

 

这部分说明简单的来说,就是只要存储过程中有一条语句发生重编译,这个 plan_generation_num 值就会 +1. 这里并没有说是整个存储过程重编译的时候,这个值会 +1.

 

接下来我们修改测试存储过程 aaa

 

Alter TABLE aaa_table(

[text] [nvarchar](max) NULL,

[sql_handle] [varbinary](64) NOT NULL,

[plan_generation_num] [bigint] NOT NULL,

[execution_count] [bigint] NOT NULL,

[dbid] [smallint] NULL,

[objectid] [int] NULL

) ON [PRIMARY]

 

insert into aaa_table select * from DMV_Top25_Recompile_Commands where 1=2

insert into aaa_table select * from DMV_Top25_Recompile_Commands where 1=2

insert into aaa_table select * from DMV_Top25_Recompile_Commands where 1=2

insert into aaa_table select * from DMV_Top25_Recompile_Commands where 1=2

insert into aaa_table select * from DMV_Top25_Recompile_Commands where 1=2

 

 

然后我们执行存储过程,收集 profiler trace ,同时继续监控性能监视器

开始重新执行存储过程 aaa

 

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

这里我们可以看到 sp recompilation/sec 立刻变成了 7

Profiler trace 中可以看到每条 insert 语句上都触发了一个 sp:recompile

 

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

 

脚本的查询结果:

 

可以看到 plan_generation_num 的值增加到 6 了。

 

为什么这样写存储过程会导致重编译? http://support.microsoft.com/kb/243586   这篇文章中列举了多种会导致存储过程重编译的情况:

aaa 这个存储过程符合这个条件:

The procedure interleaves Data Definition Language (DDL) and Data Manipulation Language (DML) operations.

 

因此我们的结论是,使用这个脚本去查询重编译次数高的存储过程是没有错的,但是这个脚本并不包含由于 sp_recompile 已经定义存储过程时使用了 with recompile 的选项而导致的存储过程重编译的情况。


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


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论