处理大型数据集和内存限制 [关闭]
Posted
技术标签:
【中文标题】处理大型数据集和内存限制 [关闭]【英文标题】:Working with large data sets and memory limitations [closed] 【发布时间】:2014-08-09 04:40:43 【问题描述】:我正在使用一些代码来比较大型对象集合并存储所有匹配项。
不出所料,我刚刚遇到了System.OutofMemoryException
我该如何解决这个问题?
在比较期间我应该写入内存,然后让其他东西将结果写入磁盘/rdbms。即创建一个缓冲区。
【问题讨论】:
您需要将集合保存在内存中吗?也许你可以给我们看一些示例代码? 尽量在内存中同时存储尽可能少的对象。确保尽快释放所有未使用的资源。尽快将不使用的数据存储在磁盘/数据库上。当一切都尽可能优化后,然后专注于硬件。确保机器有足够的 RAM 并且应用程序池有足够的分配(如果这是托管在 IIS 上的 Web 应用程序) 【参考方案1】:事实上,它确实取决于您的环境,尤其是 x86 或 x64 操作系统。在此处查看更多详细信息:Memory in depth
1.您有高级场景,您需要流式传输。确切的解决方案取决于您从哪里提取数据。如果从 SQL 数据库中提取数据,您可以使用与异步紧密耦合的 SqlDataReader 的流式传输,示例代码:
using (SqlDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess))
if (await reader.ReadAsync())
if (!(await reader.IsDBNullAsync(0)))
using (var dataStream = reader.GetStream(0))
//process the data
此链接将显示更多详细信息:Retrieving large data set。但是,请记住,这种方法会迫使您在连接字符串中使用异步以及处理异步代码,这总是会增加复杂性,尤其是当您希望通过规范/测试来覆盖它时。
2.另一种方法是批处理,即将数据缓冲到某个可接受的限制,然后将批处理公开以使用代码,然后继续获取新的一批数据,除非所有内容都已加载,示例代码:
while(true)
int count = 0;
bool canRead = reader.Read();
while(canRead)
canRead = reader.Read();
count++;
if (count >= batchSize)
break;
if (!canRead)
break;
您可以通过估计 1 行数据的大小(基于表架构,msdn article)粗略计算批处理大小,或者只是使其可配置并使用最合适的值。这种方法的主要优点是您需要对代码进行最少的更改,并且代码本身保持同步。缺点是您必须保持活动连接或每次都打开一个新连接,而是维护您已阅读的记录以及仍需要获取的记录。
最后,这两个选项都迫使您注意一些更高级的问题,例如,如果只获取了部分数据,然后连接丢失(需要一些故障转移机制),您应该怎么做(需要一些故障转移机制),取消的能力特定超时等后长时间运行的检索操作。
总而言之,如果您不想处理大数据带来的额外复杂性,请将此任务委托给市场上可用的任何东西,即数据库或第 3 方框架。如果您觉得您的团队对此有足够的技能,那么请继续自己实现它 - 将比较结果保存在磁盘文件中,利用内存缓存或将数据推送到数据库中
【讨论】:
真棒回答谢谢【参考方案2】:首先取决于您使用的处理器架构。如果您使用 32 位架构,则每个进程只有 2GB 内存。在这种情况下,您确实受到可以在那里存储的内容的限制。但是 64 位处理器允许更多内存,在这种情况下应该没问题。
另外需要注意的是,out of memory 异常并不意味着根本没有足够的内存,它意味着进程无法连续分配所需的内存块。如果您尝试分配一个非常大的对象,例如大小为 1GB 的数组,则进程需要为该 1GB 找到一个连续的内存块。
具体答案取决于您的情况,但通常我会先尝试切换到 64 位架构,然后查看分配的最大对象有多大。如果那里没有任何改进,您应该开始考虑将一些信息存储到磁盘。
【讨论】:
以上是关于处理大型数据集和内存限制 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
将大型数据集缓存到 spark 内存中时“超出 GC 开销限制”(通过 sparklyr 和 RStudio)