数据量大。迭代的最佳方法,而不会耗尽内存?

Large amount of data. Best way to iterate over, without getting memory exhaustion?

使用 Laravel 6,等等 Eloquent 集合 classes.

所以我有“大量”数据要处理。大约 5000 行,在获取它时,会生成一个包含 5000 个模型的集合。现在每个模型可能有 20 个属性需要读取。

有什么快速的方法吗?我目前有一个我想读取的属性数组,然后像这样设置循环:

\fopen()...

foreach ($models as $model) {
            $row = [];
            foreach ($this->attributes as $attr) {
                $row[] = \data_get($model, $attr);
            }
        
        \fputcsv($fh, $row);
}

\fclose()...

$models 是一个 Laravel 集合,由 EloquentModel::find($ids); 创建,其中 $ids 是一个整数数组。 (来自数据库的 5000 个 ID)

$this 指的是包含 foreach 循环的 class。 class 除了包含上述代码的函数外,没有其他内容,而 attributes 属性 只是一个字符串数组。

对于 5000 行,每行循环 20 个属性,这可能需要很长时间来处理,并且在每种情况下这实际上都会抛出一个 FatalErrorException: Allowed memory size of 134217728 bytes exhausted

那么检索每一行的属性集的最快方法是什么?我个人想不出比这个嵌套循环更快的方法了。

此外,看到 \fputcsv() 正在将每一行写入文件,并且 $row 变量在每个循环中被覆盖,为什么我仍然得到 Allowed memory size exhausted

LazyCollection 会是这里的解决方案吗?

谢谢!

这将分块处理模型,一次 200 个,从而节省大量内存。

Model::whereIn('id', $ids)->chunk(200, function($models){

      foreach ($models as $model) {
            $row = [];
            foreach ($this->attributes as $attr) {
                $row[] = \data_get($model, $attr);
            }
        
        \fputcsv($fh, $row);
      }
});