我有几个数据库管理任务需要遍历数据库中的每个记录。我的理解是,使用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()
只会减慢进程速度,但对内存使用没有帮助。
这是预期的,还是一个错误?如果是前者,有什么我可以做的不同在这段代码中来防止它吗? (显然,我可以小批量处理它,但这不是一个优雅的解决方案。)
答案 0 :(得分: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
答案 1 :(得分:0)