参数化查询的Bad Dapper性能

时间:2016-07-22 19:09:47

标签: c# performance entity-framework dapper

当我遇到一个奇怪的问题时,我正在研究将一些EF6代码移植到Dapper以获得更好的性能。单行查询在Dapper中的亮度几乎是其中的10倍。它看起来像这样:

using (IDbConnection conn = new SqlConnection("connection string"))
{                
      row = conn.Query<ReportView>("select * from ReportView where ID = @ID", 
                                          new {ID = id}))
                                  .FirstOrDefault();
}

此查询以大约80列为目标,EF版本使用相同的查询和相同的模型。作为参考,这是EF版本:

row = context.ReportViews.Where(s => s.ID == id).FirstOrDefault();

我考虑到第一个查询可能很慢,所以我在'#34;热身后'进行了测量。期。我认为重用EF模型可能是一个问题,所以我创建了一个简单的POCO作为模型。这些都没有效果。所以我玩了它,尝试了不同的东西,并决定尝试使用SQL注入的连接SQL语句。

using (IDbConnection conn = new SqlConnection("connection string"))
{                
      row = conn.Query<ReportView>(string.Format("select * from ReportView where ID = '{0}'", 
            id)).FirstOrDefault();
}

查询实际上比EF更快。

那么这里发生了什么?为什么参数化查询要慢得多?

2 个答案:

答案 0 :(得分:5)

根据您的最后一个示例,您的列似乎很可能是varchar,但是当您使用参数化查询时,参数将作为nvarchar发送。由于nvarchar到varchar可能涉及数据丢失,因此SQL会将表中的每个值转换为nvarchar以进行比较。可以想象,转换每一行进行比较的速度很慢,并且无法使用索引。

要解决此问题,您有两种选择:

如果您的数据库根本没有使用nvarchar,您只需在应用程序启动期间更改映射:

Dapper.SqlMapper.AddTypeMap(typeof(string), System.Data.DbType.AnsiString);

否则您可以按查询更改它:

row = conn.Query<ReportView>("select * from ReportView where ID = @ID", 
                              new {ID = new DbString { Value = id, IsAnsi = true }})
                              .FirstOrDefault();

答案 1 :(得分:0)

它与参数的数据类型有关。如果它与索引的那个不匹配,那么它会转换每一行来比较它。以字符串形式执行,sql解析器选择类型。