每次读取记录时内存使用量都会增加

问题描述 投票:2回答:2

我有几个数据库管理任务需要遍历数据库中的每个记录。我的理解是,使用CakePHP 3.x ORM,我可以做这样的事情,并且它一次只能在内存中有一条记录:

$records = TableRegistry::get('Whatever')->find();
foreach ($records as $record) {
    // do some processing
}

但是,这最终会因“内存不足”异常而崩溃。我添加了一些memory_get_peak_usage的日志记录,并且每次迭代都会增加,即使除了foreach循环中发生的日志记录之外什么都没有。每次循环都会有大约12K的增量。

我正在运行3.2.7,无论是否启用了调试和/或SQL日志记录,结果都是类似的。添加对gc_collect_cycles()的频繁调用只会减慢进程,但它对内存使用没有帮助。

这是预期的,还是一个错误?如果是前者,在这段代码中有什么我可以做的不同以防止它吗? (显然,我可以小批量处理它,但这不是一个优雅的解决方案。)

memory orm cakephp-3.0
2个回答
1
投票

CakePHP 3.x ORM内置了ResultSet对象的查询缓存。当您对结果集进行迭代时,实体将存储在内部数组中。这样做是为了让你可以倒回迭代器并再次循环。

如果您只想迭代一个大的结果集,并且想要减少内存使用,那么您必须禁用结果缓冲。

$records = TableRegistry::get('Whatever')->find()->bufferResults(false);
foreach ($records as $record) {
    // do some processing
}

关闭缓冲后,实体将从结果集中获取,之后不应该对其进行引用。

CakePHP书中提供了此功能的文档:https://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html#working-with-result-sets

这是API参考:https://api.cakephp.org/3.6/class-Cake.Database.Query.html#_bufferResults


0
投票

根据我的理解,这是预期的行为,当您开始迭代对象($ records)时,使用ORM执行查询构建。因此,所有数据都被加载到内存中,然后逐个迭代每个条目。

如果你想限制内存使用量,我建议你看看limitoffset。通过这些,您可以提取要处理的子集,从而限制内存使用。

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