我想知道在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 +'''?
答案 0 :(得分:2)
正如文章所建议的那样,SQL Server查询优化器可以使用sp_execute_sql的缓存执行计划。 documentation非常明确。与execute
相比,优势在于查询更有可能与计划中的某些内容相匹配。
关于计划本身的说明。查询计划是在第一次使用参数运行时生成的。这是放在缓存中的内容。对于像您这样的简单查询,查询计划应适用于后续调用。但即使在这种情况下,您可能会遇到表中包含10行和索引的情况,并且查询计划决定扫描表。当您添加另外100,000行时,它仍然希望进行扫描(直到您重新启动服务器或以其他方式清空缓存),因为这是缓存计划。
但在其他情况下,参数的值可能会影响查询计划。因此,每次重新编译查询可能不是一个坏主意。如果查询将运行任何时间长度(秒),那么编译开销可能很小。
答案 1 :(得分:1)
绑定变量的优点是,RDBMS
不需要解析/编译语句和
不需要一次又一次地评估执行计划。
通常会缓存一定数量的语句和执行计划,因此这里会节省一些时间。但是:如果你用类似的声明填充这个缓存,它将不再那么有用了。
所以最后语句本身的核心执行不会更快 - 只有周围的事情(解析,编译,创建执行计划)。
答案 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),现在你有两个计划。通过使用存储过程,您可以减轻这种担忧,因为参数定义了大小并且没有涉及猜测。