m__*_*m__ 14 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
Run Code Online (Sandbox Code Playgroud)
当我通过删除参数来修改此代码时,查询执行速度极快(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'
Run Code Online (Sandbox Code Playgroud)
buc*_*ley 28
添加OPTION(RECOMPILE)到最后
... AND SensorValue != -32767 OPTION (RECOMPILE)
Run Code Online (Sandbox Code Playgroud)
我怀疑你正在经历"参数嗅探"
如果是这种情况,我们可以将其留给OPTION或考虑替代方案
更新1
以下文章将向您介绍"参数嗅探" http://pratchev.blogspot.be/2007/08/parameter-sniffing.html
我建议你了解ins和out,因为它会让你更好地理解sql server内部(可以咬人).
如果你了解它,你就会知道,用重新编译选项的权衡可如果执行的语句是一个性能下降非常频繁.
我个人添加选项重新编译后,我知道根本原因是参数嗅探并保留它,除非存在性能问题.重写语句以避免错误的参数嗅探会导致意图丢失,从而降低可维护性.但是有些情况下重写是合理的(当你这样做时使用好的评论).
更新2
关于这个主题的最佳读物是在第32章中称为"参数嗅探:你最好的朋友......除非它不是由"GRANT FRITCHEY
这是推荐的.
我最近遇到了同样的问题.我做的第一件事是在where语句中的列上添加NonClustered Covering Index.
这改善了SQL的执行时间,但是当dapper执行查询时它仍然很慢,实际上它已经超时了.
然后我意识到由dapper生成的查询是作为nvarchar(4000)传递的参数,其中我的db表列是varchar(80)这导致它执行索引扫描而不是搜索(我建议你阅读索引,如果这对你没有意义.)意识到这一点后,我更新了我的小巧玲珑,声明如下:
WHERE Reference = convert(varchar(80),@ Reference)
使用上面的where语句执行会导致索引查找,并且性能提高100%.
只是添加:选项(重新编译)对我不起作用.
毕竟这首歌和舞蹈之后,有一种方法可以告诉dapper默认为你做这件事:
Dapper.SqlMapper.AddTypeMap(typeof(string),System.Data.DbType.AnsiString);
默认情况下,这会将任何字符串参数映射到varchar(4000)而不是nvarchar(4000).如果确实需要Unicode字符串比较,则可以显式对参数进行转换.
| 归档时间: |
|
| 查看次数: |
15716 次 |
| 最近记录: |