Sql 为估算计划绑定参数与内联值

Sql 为估算计划绑定参数与内联值,sql,sql-server,performance,sql-server-2008,database-performance,Sql,Sql Server,Performance,Sql Server 2008,Database Performance,我想知道如何在SQL查询中使用绑定参数来构建执行计划 在许多场景中,开发人员编写动态SQL查询并在查询中放置适当的值 在阅读本文时,我觉得使用绑定参数将提高性能,因为使用了相同的执行计划 下面是在SP中构造的动态查询中使用Bind参数的示例 CREATE Procedure GetEmployee AS ( @eName NVARCHAR(100), @eDept NVARCHAR(50) ) BEGIN Declare @sql NVarchar(MAX) DECLARE @params

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

在许多场景中,开发人员编写动态SQL查询并在查询中放置适当的值

在阅读本文时,我觉得使用绑定参数将提高性能,因为使用了相同的执行计划

下面是在SP中构造的动态查询中使用Bind参数的示例

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

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

绑定变量的优点是,RDBMS

  • 不需要解析/编译语句和

  • 不需要反复评估执行计划

  • 通常会缓存一定数量的状态和执行计划,这样可以节省一些时间。然而:如果你用成千上万个类似的语句来填充这个缓存,它将不再有多大帮助。
    所以最后,语句本身的核心执行不会更快,只会更快(解析、编译、创建执行计划)

    绑定变量的优点是,RDBMS

  • 不需要解析/编译语句和

  • 不需要反复评估执行计划

  • 通常会缓存一定数量的状态和执行计划,这样可以节省一些时间。然而:如果你用成千上万个类似的语句来填充这个缓存,它将不再有多大帮助。
    所以最后,语句本身的核心执行不会更快,只会更快(解析、编译、创建执行计划)

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

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


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

    正如本文所建议的,SQL Server查询优化器可以使用缓存的执行计划来执行sp_execute_SQL。这是非常明确的。与只执行
    execute
    相比,查询更有可能匹配计划中的某些内容

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


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

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

    仅仅是建立在其他人所说的基础上。进入sp_executesql计划缓存的将是一个适用于调用该方法的任何人的计划。它将为变量设置一个占位符,并在运行时应用它们。它不需要编制新的计划,这样你就可以节省成本

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

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


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

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

    仅仅是建立在其他人所说的基础上。进入sp_executesql计划缓存的将是一个适用于调用该方法的任何人的计划。