laravel 限制雄辩的块

cvxl0en2  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(88)

我有一个非常大的结果集要处理,所以我使用chunk()方法来减少作业的内存占用。但是,我只想处理一定数量的总结果,以防止作业运行时间过长。
目前我正在这样做,但它似乎不是一个优雅的解决方案:

$count = 0;
$max = 1000000;
$lists = Lists::whereReady(true);

$lists->chunk(1000, function (Collection $lists) use (&$count, $max) {
    if ($count >= $max)
        return;

    foreach ($lists as $list) {
        if ($count >= $max)
            break;

        $count++;

        // ...do stuff
    }
});

有没有更干净的方法来做到这一点?

ukxgm1gy

ukxgm1gy1#

目前为止我不这么认为
已经有一些问题和pull请求提交,以使chunk尊重先前设置的跳过/限制,但Taylor已经关闭了它们,因为chunk会覆盖这些行为。
目前在laravel/internals repo中有一个open issue,他说他会再看一看,但我不认为它在优先级列表上很高。我怀疑这是他会做的事情,但现在可能更容易接受另一个拉取请求。
你的解决方案看起来不错,除了一件事。chunk()最终将阅读整个表,除非您从闭包返回false。目前,您只是返回null,所以即使您的“max”设置为1000000,它仍然会读取整个表。如果你在$count >= $max的时候从你的闭包中return falsechunk()将停止查询数据库。它将导致chunk()本身返回false,但是您的示例代码并不关心chunk()的返回,所以这是可以的。
另一种选择,假设你使用的是顺序id,是获取结尾id,然后在分块查询中添加一个where子句,以获取所有id小于max id的记录。所以,类似于:

$max = 1000000;
$maxId = Lists::whereReady(true)->skip($max)->take(1)->value('id');

$lists = Lists::whereReady(true)->when($maxId, function($query) use ($maxId) {
    return $query->where('id', '<', $maxId);
});

$lists->chunk(1000, function (Collection $lists) {
    foreach ($lists as $list) {
        // ...do stuff
    }
});

代码稍微干净一点,但它仍然是一个黑客,需要一个额外的查询(以获得最大ID)。

相关问题