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及其改进方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对小牛知识库网站的支持!
问题内容: Java不允许覆盖静态方法,但是, 在这里没有覆盖吗? 问题答案: 这是“隐藏”,而不是“覆盖”。要看到这一点,请将方法更改为以下内容: 这应该打印: 如果正在进行真正的覆盖,那么您会看到: 通常认为使用实例类型来调用静态方法是一种不好的方式,就像您正在做的那样,因为很容易想到您正在调用实例方法,并且容易误以为重写正在发生。Java样式检查器/代码审核工具通常会将其标记为样式错误/潜在
问题内容: 因此,我正在编写另一个基于Twisted的守护程序。它会像往常一样具有xmlrpc接口,因此我可以轻松地与它进行通信,并让其他进程根据需要与它交换数据。 该守护程序需要访问数据库。我们一直在使用SQL Alchemy代替用于最新项目的硬编码SQL字符串,这些字符串大多数是为Pylons中的Web应用程序完成的。 我们想对此应用程序执行相同的操作,并重复使用利用SQL Alchemy的库
本文向大家介绍java ArrayList详解及其方法,包括了java ArrayList详解及其方法的使用技巧和注意事项,需要的朋友参考一下 Java中的ArrayList ArrayList是一个由Collection框架中的List接口实现的类。 ArrayList实现List接口,而List接口是Collection接口的子接口,因此最终ArrayList可以包含List和Collecti
本文向大家介绍Java toUpperCase()方法及其示例,包括了Java toUpperCase()方法及其示例的使用技巧和注意事项,需要的朋友参考一下 UpperCase()方法将所有字符转换为大写字母。此方法有两个变体。第一个变体使用给定Locale的规则将此String中的所有字符转换为大写。这等效于调用toUpperCase(Locale.getDefault())。 示例 现在让我
除了本书讲述的主要变化之外,ECMAScript 6 还对 JavaScript 做了一些虽小但很有意义的改进,包括简化整型的使用,新的数学运算方法,Unicode 标识符的轻微调整以及规范化 __ proto __ 属性。本附录包含以上所有的内容。 整型的使用(Working with Integers) JavaScript 使用 IEEE 754 编码系统来表示整型(integer)和浮点类
当我从egg在系统中easy_install时,这个导入工作得很好: 但是我还希望在命令行中运行,而不需要安装它(用于简短的测试等)。在这种情况下,上一次导入将失败,这是有效的: 如何处理以便在两种情况下都能工作? null