SQL Server Parameter Sniffing及其改进方法

所属分类: 数据库 / MsSql 阅读数: 1368
收藏 0 赞 0 分享

SQL Server 在处理存储过程的时候,为了节省编译时间,是一次编译,多次重用。当第一次运行时代入值产生的执行计划,不适用后续代入的参数时,就产生了parameter sniffing问题。 create procedure Sniff1(@i int) as SELECT count(b.SalesOrderID),sum(p.weight) from [Sale
SQL Server 在处理存储过程的时候,为了节省编译时间,是一次编译,多次重用。当第一次运行时代入值产生的执行计划,不适用后续代入的参数时,就产生了parameter sniffing问题。

create procedure Sniff1(@i int) as 
SELECT count(b.SalesOrderID),sum(p.weight) from 
[Sales].[SalesOrderHeader] a
inner join [Sales].[SalesOrderDetail] b
on a.SalesOrderID = b.SalesOrderID
inner join Production.Product p
on b.ProductID = p.ProductID
where a.SalesOrderID =@i;
go
DBCC FREEPROCCACHE
exec Sniff1 50000;
exec Sniff1 75124;
go

Parameter Sniffing问题发生不频繁,只会发生在数据分布不均匀或者代入参数值不均匀的情况下。现在,我们就来探讨下如何解决这类问题。

1. 使用Exec() 方式运行动态SQL

create procedure Nosniff1(@i int) as 
declare @cmd varchar(1000);
set @cmd = 'SELECT count(b.SalesOrderID),sum(p.weight) from 
[Sales].[SalesOrderHeader] a
inner join [Sales].[SalesOrderDetail] b
on a.SalesOrderID = b.SalesOrderID
inner join Production.Product p
on b.ProductID = p.ProductID
where a.SalesOrderID =';
 exec(@cmd+@i); 
go

exec Nosniff1 50000;

exec Nosniff1 75124;

从上述trace中可以看到,在执行查询语句之前,都有SP: CacheInsert事件,SQL Server做了动态编译,根据变量的值,都正确的预估了结果集,给出了不同的执行计划。

2. 使用本地变量

create procedure Nosniff2(@i int) as 
declare @iin int;
set @iin=@i
SELECT count(b.SalesOrderID),sum(p.weight) from 
[Sales].[SalesOrderHeader] a
inner join [Sales].[SalesOrderDetail] b
on a.SalesOrderID = b.SalesOrderID
inner join Production.Product p
on b.ProductID = p.ProductID
where a.SalesOrderID =@iin;
go

exec Nosniff2 50000;

exec Nosniff2 75124;

如上一篇文章所述,使用本地变量,参数值在存储过程语句执行过程中得到,SQL Server在运行时不知道变量的值,会根据一个预估值进行编译,给出一个折中的执行计划。

3. 使用Query Hint,指定执行计划

在 SELECT、DELETE、UPDATE 和 MERGE 语句最后加上OPTION ( [ ,...n ] ),对执行计划进行指导。当数据库管理员知道问题所在时,可以通过hint引导SQL Server生成一个对所有变量都不太差的执行计划。

以上所述是小编给大家介绍的SQL Server Parameter Sniffing及其改进方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

更多精彩内容其他人还在看

SQL Server正确删除Windows认证用户的方法

这篇文章主要给大家介绍了关于SQL Server正确删除Windows认证用户的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用SQL Server具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
收藏 0 赞 0 分享

SQL Server查看login所授予的具体权限问题

在SQL Server数据库中如何查看一个登录名(login)的具体权限呢,下面脚本之家小编给大家带来了SQL Server查看login所授予的具体权限问题,感兴趣的朋友一起看看吧
收藏 0 赞 0 分享

Mysql8.0.17安装教程【推荐】

本文通过图文并茂的形式给大家介绍了Mysql8.0.17安装,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

C# ling to sql 取多条记录最大时间

这篇文章主要介绍了C# ling to sql 取多条记录最大时间,文中通过实例代码给大家介绍了sql 查询相同记录下日期最大的 一条,代码简单易懂,需要的朋友可以参考下
收藏 0 赞 0 分享

sql server编写archive通用模板脚本实现自动分批删除数据

这篇文章主要介绍了sql server编写archive通用模板脚本实现自动分批删除数据,需要的朋友可以参考下
收藏 0 赞 0 分享

SQL Server怎么找出一个表包含的页信息(Page)

这篇文章主要给大家介绍了关于SQL Server是如何找出一个表包含的页信息(Page)的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用SQL Server具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
收藏 0 赞 0 分享

SQLyog连接MySQL8.0报2058错误的完美解决方法

这篇文章主要介绍了SQLyog连接MySQL8.0报2058错误的完美解决方法,本文图文并茂给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

SQL SERVER日志进行收缩的图文教程

这篇文章主要给大家介绍了关于SQL SERVER日志进行收缩的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用SQL SERVER具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
收藏 0 赞 0 分享

SqlServer中批量update语句

我现在想把S_USER表中的ACCOUNT批量修改成S_PERSON的ACCOUNT,那么就可以参考下面的语句,要找到对应的字段
收藏 0 赞 0 分享

SqlServer AS的用法

本篇文章简要分析,在SQL SERVER中,AS的基本用法,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多