我看到了很多与此有关的问题,还有马克·格雷韦尔(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首先查询数据库只是为了执行查询。然后根据读取请求再次连接到数据库,并获取特定读取的所有数据?
仅创建几个异步任务并与单个查询一起运行会更好吗?
答案 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首先查询数据库只是为了执行查询。然后根据读取请求再次连接到数据库,并获取特定读取的所有数据?
由于以下原因,始终是更好的策略:
说了这么多,我仍然感到惊讶,仅读取5万条记录是如此之慢,这必须是外部因素。切换缓冲区设置仅对5万条记录没有太大影响,它们使用二进制序列化进行了很好的压缩,通常缓冲区打开是首选设置,因为它可以优化
您必须尝试的第一件事是在相对高端的硬件,更高的RAM,更多的处理器,更好的网络IO上运行相同的测试用例,只是为了了解硬件的变化是否带来了改进,因为Dapper已经进行了优化,即使您使用DataReader
并通过QueryMultiple
阅读