首页 > 后端开发 > php教程 > 优化 Laravel 查询:分块数据的正确方法

优化 Laravel 查询:分块数据的正确方法

王林
发布: 2024-09-09 06:31:38
原创
810 人浏览过

Optimizing Laravel Queries: The Right Way to Chunk Data

为什么应该避免使用块?

最好使用 chunkById 而不是 chunk 以避免批量更新时丢失行。使用 chunk 可以在更新行后移动后续查询的偏移量,从而导致跳过未处理的行。

例如:

Post::where('processed', 0)->chunk(100, function($posts) {
    foreach($posts as $post) {
       $post->processed = 1;
       $post->save();
    }
});
登录后复制

上面的代码生成以下查询。

select * from `posts` where `processed` = 0 limit 100 offset 0
select * from `posts` where `processed` = 0 limit 100 offset 100
...
登录后复制

第一个块更新 100 行。第二个查询没有意识到这一点,因此跳过 100 个未处理的行,因为它仍然使用偏移量。

以上由
详细解释 太阮雄

如何对有限数量的行进行分块?

当尝试使用 Laravel 的 chunk() 方法处理有限数量的行时,我们可能期望以下代码只能以 2 为一组处理 5 个用户:

$query  = \App\Models\User::query()->take(5);

$query->chunk(2, function ($users) {
  // Process users
});
登录后复制

但是,这将处理数据库中的所有用户,一次两个。发生这种情况是因为 Laravel 的 chunk() 方法忽略了应用于查询的 take() 限制,导致所有行都以块的形式处理。

为了确保只在块中处理有限数量的行(例如 5 个用户),我们可以实现一个自定义索引计数器,该计数器将在达到指定限制后中断分块循环。以下代码实现了这一点:

class UserProcessor
{
    private int $index = 0;
    private int $limit = 5;

    public function process()
    {
        $query = \App\Models\User::query();

        $query->chunk(2, function ($users) {
            foreach ($users as $user) {
                $this->index++;

                // Process each user here
                // Example: $user->processData();

                if ($this->index >= $this->limit) {
                    // Stop processing after reaching the limit
                    return false;  // This will stop chunking
                }
            }
        });
    }
}
登录后复制

注意

$index 和 $limit 是类的属性,而不是通过 use($index, $limit) 传递给闭包的方法变量。这是因为通过 use() 传递的变量会按值复制到闭包对象中。因此,闭包内的任何修改都不会影响原始值,这就是为什么它们必须是类属性才能正确更新和跟踪迭代之间的更改。

以上是优化 Laravel 查询:分块数据的正确方法的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板