如何使用 Laravel 的块来避免内存不足?
Posted
技术标签:
【中文标题】如何使用 Laravel 的块来避免内存不足?【英文标题】:How do I use Laravel's chunk to avoid running out of memory? 【发布时间】:2015-03-20 20:40:31 【问题描述】:我从临时表中提取大约 10 万条记录,对数据进行一些细微修改,下载照片,然后将我需要保留的字段放入“主”表中。这很快导致我的应用程序因内存不足而崩溃。
我阅读了关于在 Laravel 雄辩的 ORM 中使用 chunk() 的非常简短的文档,但我什至不知道如何开始在我的课堂上实现它。
这是我目前正在做的事情:
public function fire()
// Turn off query logging
DB::connection()->disableQueryLog();
$feeds = RetsFeed::where('active','=',1)->get();
foreach ($feeds as $feed)
$class = "TempListing$feed->board";
$listings = $class::orderBy('MatrixModifiedDT','desc')->get();
$listings->each(function($listing) use ($feed)
ListingMigrator::migrateListing($listing,$feed);
echo "Feed: $feed->board\r\n";
echo "SubcondoName: $listing->SubCondoName\r\n";
echo "Development: $listing->Development\r\n";
echo "\r\n";
);
每个提要(或数据源)都被转储到临时表中的不同杂务中。这很好用。然后,我从一张表(平均大约 30k)中获取所有 hte 列表并运行我的 ListingMigrator 方法。
在这个例子中我应该把块放在哪里?它会取代这一行吗:
$listings = $class::orderBy('MatrixModifiedDT','desc')->get();
我不完全理解雄辩文档中的闭包。这就是他们要说的全部内容,这是来自 Laravel 网站的代码示例:
User::chunk(200, function($users)
foreach ($users as $user)
//
);
【问题讨论】:
【参考方案1】:chunk
调用应替换 get
调用 - 它旨在处理 pre-get() 查询构建器对象。
$listings = $class::orderBy('MatrixModifiedDT','desc');
$listings->chunk(200, function($listings) use($feed)
$listings->each(function($listing) use ($feed)
ListingMigrator::migrateListing($listing,$feed);
echo "Feed: $feed->board\r\n";
echo "SubcondoName: $listing->SubCondoName\r\n";
echo "Development: $listing->Development\r\n";
echo "\r\n";
);
);
【讨论】:
这似乎很有魅力!非常感谢您的慷慨回答。不过,我的一个问题是我们如何确定该块的 200 号。我的理解是,它处理了那么多,然后基本上“重新开始”,因为没有更好的词。将这个数字保持在非常低的水平,甚至是 10,难道不是安全的吗?这样做的唯一成本是额外的数据库调用吗? @ChrisFarrugia 块大小是相当随意的,唯一的硬要求是它是一个足够小的数字,因此您不会在单个块中用完 RAM。如果您的数据库不介意负载,那么 10 个块就可以了。 200 块也可以。 注意:如果chunk
涉及修改可能影响查询的记录,如软删除、硬删除、查询中的列更改等,则需要将块包围一段时间陈述。请参阅***.com/questions/32700537/… 和可能的laravel.io/forum/…
我正在运行一些包含 2000 个条目的代码。转换为 json 后,我的对象约为 150 个字节。所以这会生成整洁的 300KByte 块,这对我的数据库、所涉及的数据以及我的 php 内存和运行时限制都很有效。以上是关于如何使用 Laravel 的块来避免内存不足?的主要内容,如果未能解决你的问题,请参考以下文章