美文网首页
Laravel中chunk方法分块处理数据

Laravel中chunk方法分块处理数据

作者: 积_渐 | 来源:发表于2019-01-24 16:37 被阅读20次

    在一些情况下,我们需要对大批量的数据进行操作,如果这个时候我们使用foreach的话,很可能会遇到操作超时的情况。
    在Laravel框架中我们可以很方便的使用chunk方法来解决。
    来看一个简单的例子:

    $users = User::all();
    foreach ($users as $user) {
      $some_value = ($user->some_field > 0) ? 1 : 0;
      // 一些其他的逻辑
      $user->update(['some_other_field' => $some_value]);
    }
    

    这段代码看起来并没有什么不对,但是当数据量很大的时候,情况就不那么乐观了,一方面是运行时间,再者要考虑数据存储时内存消耗完。
    在Laravel中,应用chunk将数据分块的方法,可以很好的处理这种问题,下面是应用chunk的代码:

    User::chunk(100, function ($users) {
      foreach ($users as $user) {
        $some_value = ($user->some_field > 0) ? 1 : 0;
        // might be more logic here
        $user->update(['some_other_field' => $some_value]);
      }
    });
    

    这段代码是执行一个100条的数据进行更新,当执行完成后继续后面的另一百条数据……
    也就是说他每次操作的是一个数据块而不是整个数据库。

    User::chunk(100, function ($users) {
      foreach ($users as $user) {
        $some_value = ($user->some_field > 0) ? 1 : 0;
        // might be more logic here
        $user->update(['some_other_field' => $some_value]);
      }
    });
    

    需要注意的是:当使用带筛选的条件的chunk时,如果是自更新,那么你会漏掉一些数据,接着看代码:

    User::where('approved', 0)->chunk(100, function ($users) {
      foreach ($users as $user) {
        $user->update(['approved' => 1]);
      }
    });
    

    如果要运行上面的代码,并不会有报错,但是where条件是筛选approved为0的user然后将approved的值跟新为1。
    在这个过程中,档第一数据库的数据被修改后,下一个数据块的数据将是在被修改后的数据中选出来的,这个时候数据变了,而page也加了1。所以执行结束后,只对数据中一半的数据进行了更新操作。
    如果没有明白的话,我们来看一下chunk的底层实现。还以上面的代码为例,假如一共有400条数据,数据被按照100条进行分块处理。
    page = 1: 最开始的时候page为1,选取1-100条数据进行处理;
    page = 2: 这时候前一百数据的approved值全部为1,那么在次筛选的时候数据将从第101条开始,而这个时候的page=2,那么处理的数据将是第200-300之前的数据
    之后依旧。

    public function chunk($count, callable $callback)
    {
        $results = $this->forPage($page = 1, $count)->get();
        while (count($results) > 0) {
            // On each chunk result set, we will pass them to the callback and then let the
            // developer take care of everything within the callback, which allows us to
            // keep the memory low for spinning through large result sets for working.
            if (call_user_func($callback, $results) === false) {
                return false;
            }
            $page++;
            $results = $this->forPage($page, $count)->get();
        }
        return true;
    }
    

    原文地址

    相关文章

      网友评论

          本文标题:Laravel中chunk方法分块处理数据

          本文链接:https://www.haomeiwen.com/subject/mjhujqtx.html