2

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

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

在阅读本文时,http://use-the-index-luke.com/sql/where-clause/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

与 WHERE Name='''+@eName+''' 相比,这如何真正提高性能?

4

3 回答 3

2

正如文章所建议的,SQL Server 查询优化器可以为 sp_execute_sql 使用缓存的执行计划。该文档非常明确。与 just 相比的优点execute是查询更有可能匹配计划中的某些内容。

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

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

于 2013-02-23T17:57:05.703 回答
1

绑定变量的优点是,RDBMS

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

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

通常会缓存一定数量的语句和执行计划,因此可以节省一些时间。然而:如果你用成千上万个类似的语句填满这个缓存,它就不会再有太大帮助了。

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

于 2013-02-23T17:53:50.993 回答
1

与 WHERE Name='''+@eName+''' 相比,这如何真正提高性能?

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

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

拥有这些独特计划的缺点是会占用其他计划缓存的可用内存。计划不在缓存中?必须编译,哎呀,计划缓存已满,是时候选择最近最少使用的计划并将其踢出。下一个查询进来了,它需要我们刚刚装箱的计划,并且计划缓存交换循环继续进行。

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

于 2013-02-23T20:46:35.353 回答