sp_executesql是参数部分的长度定义发生变化能否重用执行计划
去年techtalk的时候有同事问了我一个问题:使用sp_executesql是参数部分的长度定义发生变化能否重用执行计划。当时回答不能,但当时并没有给出示例,其实自己也没有尝试过。今天把实验代码贴出来
准备工作
create table dbo.ta(id varchar(10) ,c char(10))
go
insert dbo.ta
select ROW_NUMBER() over(order by c1.name) id,'x' from sys.columns c1 cross join sys.columns c2
go
create index index1 on dbo.ta(id)
go
dbcc freeproccache
go
go
insert dbo.ta
select ROW_NUMBER() over(order by c1.name) id,'x' from sys.columns c1 cross join sys.columns c2
go
create index index1 on dbo.ta(id)
go
dbcc freeproccache
go
接下来要用select *from ta where id='1'的方式执行两次,看看是否重用了存储过程
dbcc freeproccache
go
DECLARE @value varchar(1);
DECLARE @SQLString nvarchar(500);
DECLARE @ParmDefinition nvarchar(500);
/* Build the SQL string one time.*/
SET @SQLString =
N'select * from dbo.ta
WHERE id = @id';
SET @ParmDefinition = N'@id varchar(1)';
/* Execute the string with the first parameter value. */
SET @value = '1';
EXECUTE sp_executesql @SQLString, @ParmDefinition,
@id = @value;
go
DECLARE @value varchar(2);
DECLARE @SQLString nvarchar(500);
DECLARE @ParmDefinition nvarchar(500);
/* Build the SQL string one time.*/
SET @SQLString =
N'select * from dbo.ta
WHERE id = @id';
SET @ParmDefinition = N'@id varchar(2)';
/* Execute the string with the first parameter value. */
SET @value = '10';
EXECUTE sp_executesql @SQLString, @ParmDefinition,
@id = @value;
go
go
DECLARE @value varchar(1);
DECLARE @SQLString nvarchar(500);
DECLARE @ParmDefinition nvarchar(500);
/* Build the SQL string one time.*/
SET @SQLString =
N'select * from dbo.ta
WHERE id = @id';
SET @ParmDefinition = N'@id varchar(1)';
/* Execute the string with the first parameter value. */
SET @value = '1';
EXECUTE sp_executesql @SQLString, @ParmDefinition,
@id = @value;
go
DECLARE @value varchar(2);
DECLARE @SQLString nvarchar(500);
DECLARE @ParmDefinition nvarchar(500);
/* Build the SQL string one time.*/
SET @SQLString =
N'select * from dbo.ta
WHERE id = @id';
SET @ParmDefinition = N'@id varchar(2)';
/* Execute the string with the first parameter value. */
SET @value = '10';
EXECUTE sp_executesql @SQLString, @ParmDefinition,
@id = @value;
go
查看执行计划
SELECT execution_count,
SUBSTRING(st.text, (qs.statement_start_offset/2)+1,
((CASE qs.statement_end_offset
WHEN -1 THEN DATALENGTH(st.text)
ELSE qs.statement_end_offset
END - qs.statement_start_offset)/2) + 1) AS statement_text
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
where st.text not like '%dm_exec_sql_text%'
执行结果如下:
execution_count statement_text
-------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 select * from dbo.ta
WHERE id = @id
1 select * from dbo.ta
WHERE id = @id
(2 行受影响)
说明长度发生变化无法重用计划
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
2010-01-05 一些DOS命令