我正在一个新项目中使用 dapper,并且很喜欢它,但我不明白为什么我的查询真的很慢。执行时间非常快,几乎是即时的,但是当 dapper 将结果映射到我的对象时,连接保持打开状态的时间要长得多。我猜。
这是一瞥的例子:
此查询只是对 15 个字段(主键上有一个 where)的 SELECT,因此执行速度非常快,并且不会返回那么多数据。 我的执行代码是:
using (var conn = GetConnection())
{
obj = conn.Get<T>(id);
}
该对象是一个非常基本的 poco,包含字符串和整数。 那么为什么我要浪费 220 毫秒来执行此操作,而查询执行本身需要 3 毫秒呢?区别在哪里?
感谢您的帮助!
更新
我的 SQL 语句的选择部分中有一个字段给我带来了问题。我只是一一删除每个字段,然后找到导致问题的字段。
我必须将我的字段之一转换为 nvarchar,如下所示:
CAST(my_field AS nvarchar(max)) as my_field
原答案
它必须与映射做一些事情。因为如果我将其从“强类型”更改(这将永远花费大约 1 分钟):
var products = connection.Query<Product>(sql).ToList();
致“匿名者”:
var products = connection.Query(sql).ToList();
然后它执行得非常快(1秒)。
我尝试直接在“SQL Server Management Studio”中作为查询执行 SQL 语句,并且在不到 1 秒的时间内完成。
所以我的建议是,您使用“匿名映射”,直到精明的家伙能够解决这个问题。
当我尝试从 View 投影到 POCO 对象时,我对 Dapper 也有类似的经历。
问题最终对我来说是,我的对象上的每个属性都没有一列,所以
Convert.ChangeType()
非常慢,我在我的视图中添加了一列,它总是返回NULL
,并且Query<T>()
通话速度显着加快。
在我的示例中,数据库有一个类型为
VARCHAR(10)
的索引列。我试图通过 dapper 参数进行过滤,如下所示:
DbConnection con = ...
string filterParam = "test";
var results = con.Query("SELECT IndexColumn, Column1, ... FROM MyTable WHERE IndexColumn = @filterParam", new { filterParam });
问题是 dapper(或可能是 ADO.Net)将我的
filterParam
转换为 NVARCHAR(MAX)
数据类型。然后,Sql Server 将 IndexColumn
转换为 NVARCHAR
,并进行全表扫描而不是索引查找。通过在比较之前转换参数来修复代码:
var results = con.Query("SELECT IndexColumn, Column1, ... FROM MyTable WHERE IndexColumn = CAST(@filterParam AS VARCHAR(10))", new { filterParam });
就我而言,性能不佳似乎是由于我在执行
SELECT
时使用星号而不是字段列表(即 SELECT *
而不是 SELECT Foo, Bar, Baz, ...
)而造成的。
参数似乎也会降低性能。 T-SQL 在 SSMS 中执行时间为 5 秒,对近 250 万行进行分组,从 Dapper 执行时,AVGed 长达 1-2 分钟。
await db.QueryAsync("SELECT * FROM [dbo].[DefaultReport](@StartDate, @EndDate)", new { StartDate = fromDate, EndDate = toDate })
我更改了上面的代码,删除了参数并将参数作为字符串的一部分传递(针对 SQL 格式化,比如说 yyyyMMdd)
await db.QueryAsync("SELECT * FROM [dbo].[DefaultReport]('20200101', '20240101')")
现在执行时间是5-10秒(取决于机器业务),原来是1-2分钟。