sp_executesql参数很慢

时间:2012-06-07 13:59:20

标签: sql-server dapper

我使用dapper-dot-net作为ORM,它产生以下,执行速度慢(1700ms)的SQL代码。

exec sp_executesql N'SELECT TOP 5 SensorValue FROM "Values" WHERE DeviceId IN (@id1,@id2) AND SensorId = @sensor AND SensorValue != -32768 AND SensorValue != -32767',N'@id1 bigint,@id2 bigint,@sensor int',@id1=139,@id2=726,@sensor=178

当我通过删除参数来修改此代码时,查询执行速度极快(20ms)。缺乏这些参数是否真的会产生这么大的差异?为什么呢?

exec sp_executesql N'SELECT TOP 5 SensorValue FROM "Values" WHERE DeviceId IN (139,726) AND SensorId = 178 AND SensorValue != -32768 AND SensorValue != -32767'

2 个答案:

答案 0 :(得分:26)

将OPTION(RECOMPILE)添加到结尾

... AND SensorValue != -32767 OPTION (RECOMPILE) 

我怀疑你正在体验“参数嗅探”

如果是这种情况,我们可以将其留给OPTION或考虑替代方案

更新1

以下文章将向您介绍“参数嗅探”http://pratchev.blogspot.be/2007/08/parameter-sniffing.html

我建议您了解ins和out,因为它会让你更好地理解sql server内部(可以咬人)。

如果您了解它,您将知道如果语句经常执行非常,那么使用选项重新编译的权衡可能会降低性能。

我个人在之后添加选项重新编译我知道根本原因是参数嗅探并保留它,除非存在性能问题。重写语句以避免错误的参数嗅探会导致意图丢失,从而降低可维护性。但有些情况下重写是合理的(当你这样做时使用好的评论)。

更新2

关于这个问题的最佳读物是在第32章中被称为 “参数嗅探:你最好的朋友......除非它不是由GRANT FRITCHEY提供的

建议。

SQL Server MVP Deep Dives, Volume 2

答案 1 :(得分:6)

我最近遇到了同样的问题。我做的第一件事是在where语句中的列上添加NonClustered Covering Index。

这改善了SQL的执行时间,但是当dapper执行查询时它仍然很慢,实际上是超时。

然后我意识到dapper生成的查询正在传递参数为 nvarchar(4000),其中我的db表列是varchar(80),这导致它执行索引扫描而不是搜索< / strong>(如果对你没有意义,我建议你阅读索引。)在意识到这一点后,我更新了我的小巧玲珑,声明如下:

  

WHERE Reference = convert(varchar(80),@ Reference)

执行上面的where语句会导致索引搜索,并且性能提升100%。

刚添加:选项(重新编译)对我不起作用。

在完成所有这首歌和舞曲之后,有一种方法可以告诉dapper默认为你做这件事:

  

Dapper.SqlMapper.AddTypeMap(typeof运算(字符串),   System.Data.DbType.AnsiString);

默认情况下,这会将任何字符串参数映射到varchar(4000)而不是nvarchar(4000)。如果确实需要Unicode字符串比较,则可以显式对参数进行转换。