我一直在阅读查询计划以及如何最小化SQL Server为同一基本查询创建的重复计划。例如,如果我理解正确,发送带有内联值的查询可能会产生2个不同的查询计划。超简范例:
"SELECT FirstName FROM Members WHERE LastName = 'Lee'"
"SELECT FirstName FROM Members WHERE LastName = 'MacGhilleseatheanaich'"
使用存储过程可以避免这种情况,因为它可以确保查询哈希值相同。 “LastName”作为参数传递,例如:
CREATE PROCEDURE sp_myStoredProcedure
@LastName varchar(100)
AS
SELECT FirstName FROM Members WHERE LastName = @LastName
Go
现在,我的问题是这是否适用于Command对象(例如ADO.NET中的SQLClient.SQLCommand)。我问的原因是字符串参数没有定义的最大长度,如上面的代码所示。请使用以下代码:
MyCmd.CommandText = "SELECT FirstName FROM Members WHERE LastName = @LastName"
MyCmd.Parameters.AddWithValue("@LastName", "Lee")
然后:
MyCmd.Parameters.Clear()
MyCmd.Parameters.AddWithValue("@LastName", "MacGhilleseatheanaich")
由于@LastName尚未向SQL Server声明为具有已定义的最大长度,因此当我以这种方式执行命令时,SQL Server是否会为每个不同的值创建一个新的查询计划?
我的问题主要来自于阅读.NET 3.5中的LINQ2SQL如何通过定义不同的参数长度(http://damieng.com/blog/2009/12/13/sql-server-query-plan-cache)来错过缓存。由于在使用Command对象时未定义长度,它是否会共享相同的问题?
答案 0 :(得分:4)
您的参数化查询实际上是作为对系统存储过程sp_executesql
的调用发送到服务器的,该系统存储过程非常善于尝试通过比较未填充的哈希值来重用查询计划1} em>语句掩码与计划的语句掩码仍然存在于缓存中,因此如果它可能并且如果服务器认为它是合适的,那么很有可能计划重用(并且可能还有参与者嗅探问题)。
另外值得一提的是Simple Parameterization几乎可以保证你第一个例子中的两个陈述实际上最终会使用相同的计划。
答案 1 :(得分:0)
可以在SP中添加查询提示,以控制何时 - 如何 - 创建QEP。这可能无法解决您的特定问题(或者确实可以回答您的具体问题!)但网上有很多关于此问题的信息,例如: http://msdn.microsoft.com/en-us/library/ms190727.aspx