SQL - 使用常量值与参数的任何性能差异?

pkr*_*298 5 sql sql-server sql-server-2012

关于性能,当有多个查询在where子句中运行(不同的)常量值时,是否存在任何差异,而不是在顶部有一个带有声明参数的查询,而参数值正在改变?

在where子句中使用常量值的示例查询:

select
*
from [table]
where [guid_field] = '00000000-0000-0000-000000000000' --value changes
Run Code Online (Sandbox Code Playgroud)

使用声明的参数提出(改进?)查询:

declare @var uniqueidentifier = '00000000-0000-0000-000000000000' --value changes

select
*
from [table]
where [guid_field] = @var
Run Code Online (Sandbox Code Playgroud)

有什么区别吗?我正在查看类似于上述两个查询的执行计划,我看不出任何区别.但是,我似乎记得,如果你在SQL语句中使用常量值,那么SQL服务器将不会重用相同的查询执行计划,或者那种导致性能更差的东西 - 但这是否真的如此?

Gar*_*thD 2

这里区分参数和变量很重要。参数被传递给过程和函数,变量被声明。

解决变量问题,这就是问题中的 SQL 所具有的,在编译临时批处理时,SQL Server 会在其自己的权限内编译每个语句。因此,当使用变量编译查询时,它不会返回检查任何赋值,因此它将编译针对未知变量优化的执行计划。第一次运行时,此执行计划将被添加到计划缓存中,然后将来的执行可以并将此缓存重用于所有变量值。

当您传递常量时,查询将根据该特定值进行编译,因此可以创建更优化的计划,但会增加重新编译的成本。

所以具体回答你的问题:

然而,我似乎记得,如果您在 SQL 语句中使用常量值,那么 SQL Server 将不会重用相同的查询执行计划,或者会导致性能更差 - 但这实际上是真的吗?

是的,同一计划确实不能重复用于不同的常量值,但这并不一定会导致性能更差。对于该特定常量,可能可以使用更合适的计划(例如,对于稀疏数据,选择书签查找而不是索引扫描),并且此查询计划更改可能会超过重新编译的成本。关于 SQL 性能问题几乎总是如此。答案是视情况而定

对于参数,默认行为是根据首次执行过程或函数时使用的参数的时间来编译执行计划。

我之前已经通过示例更详细地回答了类似的问题,这些示例涵盖了上述内容,因此我不会重复其各个方面,而是将问题链接起来: