调用 Dapper 的 QueryAsync<>() 方法时出现 System.OutOfMemoryException

问题描述 投票:0回答:1

我的问题

在我的日志中,我看到在负载测试期间记录了一些 System.OutOfMemoryException 错误。它们来自 Dapper 查询。根据堆栈跟踪,调整列表大小时会发生错误。

堆栈跟踪的顶部

System.OutOfMemoryException:引发了“System.OutOfMemoryException”类型的异常。 在 System.Collections.Generic.List

1.set_Capacity(Int32 value) at System.Collections.Generic.List
1.AddWithResize(T 项目) 在 C:\projects\dapper\Dapper\SqlMapper.Async.cs:line 442

被调用的代码

const string sql = $@"
  SELECT [Column 1]
        ,[Column 2]
        ,[Column 3]
        ,[Column 4]
        ,[Column 5]
        ,[Column 6]
        ,[Column 7]
        ,[Column 8]
        ,[Column 9]
        ,[Column 10]
        ,[Column 11]
        ,[Column 12]
    FROM [MyDb].[MyTable]
    WHERE co = @CompanyId AND process = @Process
    ";

await using var connection = _dbConnectionProvider.Create(DbKey.MyDb);

var parameters = new { CompanyId = CompanyDbString(companyId), Process = process };
var command = new CommandDefinition(sql, parameters);
var results = await connection.QueryAsync<MyEntity>(command); // error happens here

return results;

有关正在加载的数据的一些信息

我查看了数据库,发现有问题的数据大小为 141,846 行。这些列没有什么“不寻常的”(没有巨大的文本斑点或类似的东西),只是一些合理的 varchars、datetimes、ints 等。所有 varchars 最多 100 个字符。

只是为了避免不可避免的“你真的需要加载所有数据吗?”萌芽中的评论:是的,我愿意。

可能的解决方案?

所以,加载的数据是一个相当大的数据集,但没有什么疯狂的。我很惊讶它内存不足。我发现特别有趣的是异常源于

System.Collections.Generic.List1.set_Capacity(Int32 value)
。基于此,看起来错误发生在列表调整其内部数组大小时。

关于如何解决这个问题,我的第一个想法是对结果进行分页,这是这里的建议:https://stackoverflow.com/a/52212051

但是,我不确定这是否可行,因为它仍然依赖于添加到的列表。这是一个合理的担忧吗?如果是这样,首先获取计数并以此作为初始容量开始列表是不是一个好方法?

或者是否有一个不同的集合比 List 更适合调整大小/内存?

c# memory out-of-memory dapper
1个回答
0
投票

你需要做一个无缓冲的 Dapper 查询,并将结果插入到一个预先确定大小的列表中。

var list = new List<MyEntity>(someBigSizeHere);
var command = new CommandDefinition(sql, parameters) { Buffered = false };
using var results = await connection.QueryAsync<MyEntity>(command);
list.AddRange(results);
return list;

请注意,您必须确保在关闭连接之前完全阅读并处理

results

如果在此之后你仍然遇到内存不足的异常,那么你根本没有足够的数据。尝试编译为 64 位并向系统添加更多 RAM。或者更好:重新思考为什么需要这么多数据。

© www.soinside.com 2019 - 2024. All rights reserved.