Dapper多个查询读取速度很慢

时间:2018-10-25 13:02:06

标签: c# sql-server dapper

我看到了很多与此有关的问题,还有马克·格雷韦尔(Marc Gravell)解释了为什么他不想继续在精巧的小巧格上玩多重格。

但是我只想了解一些东西

var grid = context.QueryMultiple(string.Join(" ; ", selectCommands));
return queries.Select(q => grid.Read<T>()).AsList();

在这种情况下,执行QueryMultiple大约需要3秒钟(这在SQL上几乎是执行时间),而具有2个查询的网格读取首先需要3秒钟,然后需要9秒钟。

每行大约有5万行,只有5列,其中2列为int,2列为double(在SQL上为float)和日期时间。 我试图关闭缓冲,但并没有帮助。

这是因为Dapper首先查询数据库只是为了执行查询。然后根据读取请求再次连接到数据库,并获取特定读取的所有数据?

仅创建几个异步任务并与单个查询一起运行会更好吗?

1 个答案:

答案 0 :(得分:3)

  

我看到了很多有关此的问题,以及马克·格雷韦尔(Marc Gravell)解释了为什么他不想继续使用精巧的多格游戏

最可能的原因是,尽管我们使用MARS - Multiple Active Result Sets执行查询会产生多个结果,但是仍然无法一次性访问所有结果集。它们可以通过使用NextResult的{​​{1}}功能在内部执行,因此可以按顺序读取。对于应用程序,它仍然是1个调用,理想情况下,使用多个异步调用的同一事物将始终并行获取所有结果集(理想的系统/资源使用情况)

  

关于您的查询:

DataReader

我假设您的所有结果集都是相同的queries.Select(q => grid.Read<T>()).AsList();,而您要提取的最终结果的类型为type T

现在所拥有的选项是使用List<IEnumerable<T>>修改查询,如下所示:

Async-Await
  

有什么帮助吗?

在一定程度上,通过使操作异步进行,但好处是有限的,因为使用MARS读取仍然是顺序的。

现在是查询的主要部分,

  

在这种情况下,执行QueryMultiple大约需要3秒钟(这在SQL上几乎是执行时间),而具有2个查询的网格读取首先需要3秒钟,然后需要9秒钟。

这是令人惊讶的,读取是唯一完成的操作,查询已执行。我们正在使用var grid = await context.QueryMultipleAsync(string.Join(";",selectCommands)); return queries.Select(q => await grid.ReadAsync<T>()).AsList(); ,它已经是一个连接者,与Dapper DataReader相同,后者是GridReader的包装器。如果仅读取需要花费大量时间,甚至对于5万条记录也是如此,那么您可能想找出其他有影响力的参数,例如网络IO速度,是否达到内存/ RAM限制,这是影响巨大的外部因素。

  

这是因为Dapper首先查询数据库只是为了执行查询。然后根据读取请求再次连接到数据库,并获取特定读取的所有数据?

由于以下原因,始终是更好的策略:

  1. 高度可扩展的方法
  2. 数据库可以根据其设计一起执行多个查询
  3. 不顺序收集/读取结果

说了这么多,我仍然感到惊讶,仅读取5万条记录是如此之慢,这必须是外部因素。切换缓冲区设置仅对5万条记录没有太大影响,它们使用二进制序列化进行了很好的压缩,通常缓冲区打开是首选设置,因为它可以优化


编辑1

您必须尝试的第一件事是在相对高端的硬件,更高的RAM,更多的处理器,更好的网络IO上运行相同的测试用例,只是为了了解硬件的变化是否带来了改进,因为Dapper已经进行了优化,即使您使用DataReader并通过QueryMultiple阅读