绑定参数Vs估计计划的内联值

时间:2013-02-23 17:39:34

标签: sql sql-server performance sql-server-2008 database-performance

我想知道在SQL查询中使用绑定参数来构建执行计划。

在许多情况下,开发人员编写动态SQL查询并在Query中放置适当的值。

在阅读本文时,http://use-the-index-luke.com/sql/where-clause/bind-parameters我觉得使用Bind Parameters会因为使用相同的执行计划而提高性能。

以下是在SP中构建动态查询中的绑定参数的示例。

CREATE Procedure GetEmployee 
AS
(
@eName NVARCHAR(100),
@eDept NVARCHAR(50)
)

BEGIN
Declare @sql NVarchar(MAX)
DECLARE @params NVARCHAR(MAX)

 SELECT @params = N'@name nvarchar(100), ' +  
                    N'@dept nvarchar(50) ' 

SET @sql='Select EmpId, Name from Employee where Name=@name AND Department=@dept'

sp_executesql @sql, @params, @eName, @eDept

END

这如何真正提升效果与姓名='''+ @ eName +'''?

3 个答案:

答案 0 :(得分:2)

正如文章所建议的那样,SQL Server查询优化器可以使用sp_execute_sql的缓存执行计划。 documentation非常明确。与execute相比,优势在于查询更有可能与计划中的某些内容相匹配。

关于计划本身的说明。查询计划是在第一次使用参数运行时生成的。这是放在缓存中的内容。对于像您这样的简单查询,查询计划应适用于后续调用。但即使在这种情况下,您可能会遇到表中包含10行和索引的情况,并且查询计划决定扫描表。当您添加另外100,000行时,它仍然希望进行扫描(直到您重新启动服务器或以其他方式清空缓存),因为这是缓存计划。

但在其他情况下,参数的值可能会影响查询计划。因此,每次重新编译查询可能不是一个坏主意。如果查询将运行任何时间长度(秒),那么编译开销可能很小。

答案 1 :(得分:1)

绑定变量的优点是,RDBMS

  1. 不需要解析/编译语句和

  2. 不需要一次又一次地评估执行计划。

  3. 通常会缓存一定数量的语句和执行计划,因此这里会节省一些时间。但是:如果你用类似的声明填充这个缓存,它将不再那么有用了。

    所以最后语句本身的核心执行不会更快 - 只有周围的事情(解析,编译,创建执行计划)。

答案 2 :(得分:1)

这如何真正提高性能Vs WHERE Name ='''+ @ eName +'''?

简单地以其他人所说的为基础。 sp_executesql的计划缓存中的内容将是适用于调用该方法的任何人的计划。它将具有变量的占位符并在运行时应用它们。它不需要编译新计划,因此您可以节省成本。

此外,这可能是一个很大的不同,与前者相比,将为所有传入的变量组合生成 1 计划。后者,您将获得每个变量组合的1个查询计划。它可能在逻辑上与应用的Index Seek,Sort等操作符相同,但是不是计划中的占位符,eName ='Bob'将有一个计划,eName ='William',等

拥有这些独特计划的缺点是会占用其他缓存计划的可用内存。计划不在缓存中?需要编译和oops,计划缓存已满,是时候选择最近最少使用的计划并将其解决。下一个查询进来,它需要我们刚刚分区的计划,并且计划缓存交换周期继续。

关于至少.NET方面的事情要注意的最后一件事。在链接的示例中,这行代码cmd.Parameters.AddWithValue("@subsidiary_id", subsidiary_id);很好,因为它处理的是整数。 Int是整数。但是,如果您要在上面内联查询,参数@eName@eDepartment可能会导致不同的查询计划,因为AddWithValue方法会做一些猜测而且可能不会来为您的变量提供一致的定义。它可能决定一个是nvarchar(30)而下一个是nvarchar(29),现在你有两个计划。通过使用存储过程,您可以减轻这种担忧,因为参数定义了大小并且没有涉及猜测。