Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL Server 2014性能-参数化SQL与文字_Sql_Sql Server - Fatal编程技术网

SQL Server 2014性能-参数化SQL与文字

SQL Server 2014性能-参数化SQL与文字,sql,sql-server,Sql,Sql Server,我有一个简单的问题,比如 select count(distinct key) from table where date between '2014-01-01' and '2014-12-31' 它很快(大约1秒),但当我尝试在sp_executesql中对其进行参数化时,速度会慢得多(大约4秒): exec sp_executesql N'select count(distinct key) from table where date between @start and

我有一个简单的问题,比如

select count(distinct key) 
from table 
where date between '2014-01-01' and '2014-12-31'
它很快(大约1秒),但当我尝试在
sp_executesql
中对其进行参数化时,速度会慢得多(大约4秒):

exec sp_executesql 
     N'select count(distinct key) from table where date between @start and @end', 
     N'@start date, @end date',
     @start = '2014-01-01', @end='2014-12-31'
为什么性能会有差异

更新计划差异似乎是因为类型转换。当我将参数类型更改为N'@start datetime,@end datetime',以精确匹配列时,差异消失,参数与常量的计划实际上是相同的(相同的成本等)(Facepalm)

我将接受一个答案,解释为什么类型转换会导致如此巨大的计划差异,而不仅仅是预先转换参数并照常进行

结束更新

这些计划非常相似——相同的索引、相同的估计基数、相同的行计数和相同的I/O——尽管参数化版本中的CPU成本估计更高

具体差异:

  • 在两个计划中都会出现相同的索引搜索,但在具有文字的(快速)版本中是并行的,而在具有参数的(慢速)版本中不是并行的。非并行处理器具有较高的CPU估计
  • 带有参数的版本有一个嵌套的循环联接,它将索引扫描与参数周围的一些逻辑连接起来。这似乎增加了自己的一些CPU开销(嵌套循环中的CPU估计值=7.6)
  • 两个版本都将“并行性”作为哈希匹配的子级;在参数化版本中,它是分布式流(CPU估计值=16.5),但在文本版本中,它是重新分区流(CPU估计值=8.3)
如何使参数化版本的性能与具有文本的版本类似

在我关于参数化查询性能的研究中,我所能找到的一切都与估计有关——要么是使用不同的参数值缓存的计划,要么是将局部变量视为未知数。这两者都不是一个因素;我的估计是正确的

为什么性能会有差异

因为您有两个不同的查询,它们有两个不同的执行计划(即使它们相似)

为什么你有两个不同的计划

Erland Sommarskog有一篇非常详细的文章,解释了查询优化器的工作原理。适用于您的示例的关键点包括:

  • 常量是常量,当查询包含常量时,SQL Server可以完全信任该常量的值,甚至 如果表可以从中推断,则使用这些快捷方式根本不访问表 不返回任何行的约束

  • 对于参数,SQL Server不知道运行时值,但在编译查询时会“嗅探”输入值

  • 对于局部变量,SQL Server完全不知道运行时值,并应用标准假设。(假设是什么 取决于运算符,以及可以从 唯一索引。)

这有一个推论:如果从 存储过程,并用常量替换变量和参数, 您现在有了一个完全不同的查询

如文章“快速回答”所示:

如何使参数化版本的性能与 文字版本

就是使用

重新编译

指示SQL Server数据库引擎放弃生成的计划 对于执行后的查询,强制查询优化器 下次执行同一查询时重新编译查询计划。 不指定重新编译,数据库引擎缓存查询计划 并重复使用它们。编译查询计划时,重新编译查询提示 使用查询中任何局部变量的当前值,如果 查询位于存储过程中,当前值传递给 任何参数

所以,选项
RECOMPILE
的行为就像查询具有文本值而不是参数一样

针对优化

指示查询优化器对本地查询使用特定值 编译和优化查询时的变量。使用该值 仅在查询优化期间,而不是在查询执行期间


你能粘贴执行计划xml吗?复制帖子?稍有不同的问题。我修复了最初的估算问题和tempdb溢出,但是在文本和参数化SQLI之间仍然存在性能差异。我明白了,我很抱歉。问题是什么?这是一个典型的参数化问题。你研究过这个吗?为什么您不能使用常用的解决方案?谢谢,这是一个有用的资源。我已经发现了局部变量和参数之间的差异,这导致了基数估计的问题。使用使用不同参数编译的查询也可能是一个问题。在我的例子中,这两个问题都不是。我认为“如何使参数化版本的性能与文本版本类似?”的答案是:使用
选项(重新编译)
。当您对参数使用此选项时,您是否获得与文字相同的计划和性能?