Laravel中的chunk组块结果集处理与注意问题


Posted in PHP onAugust 15, 2018

前言

如果你需要处理成千上万个 Eloquent 结果,可以使用 chunk 命令。chunk 方法会获取一个“组块”的 Eloquent 模型,并将其填充到给定闭包进行处理。使用 chunk 方法能够在处理大量数据集合时能够有效减少内存消耗:

Flight::chunk(200, function ($flights) {
 foreach ($flights as $flight) {
  //
 }
});

$all_ark=Arkvolume::chunk(50000, function ($flights) {
 foreach ($flights as $flight) {
  $GLOBALS['something'][] = $flight['id'];
 }
});
 
var_dump($GLOBALS['something'] );exit;

这段代码是执行一个100条的数据进行更新,当执行完成后继续后面的另一百条数据……

也就是说他每次操作的是一个数据块而不是整个数据库。

需要注意的是:当使用带筛选的条件的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 使用注意的问题

使用 Laravel 的 chunk 可以用来优化大结果集的查询,提供分块处理数据的方法,但是如下的例子就会有问题:

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

原因在于第一次查询:

select * from users where approved = 0 limit 100 offset 0;

update 这一批数据的 approved 为 1 之后,

再看第二次查询:

select * from users where approved = 0 limit 100 offset 100;

这个时候因为有 where approved = 0 条件并且偏移量从 100 开始,这样其实就漏掉了 100 条 approved 为 0 的数据。

所以,我们要避免使用 chunk 的时候,更改和过滤条件的字段的值。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
PHP的autoload自动加载机制使用说明
Dec 28 PHP
php去掉字符串的最后一个字符附substr()的用法
Mar 23 PHP
生成随机字符串和验证码的类的PHP实例
Dec 24 PHP
php简单实现MVC
Feb 05 PHP
PHP中基本HTTP认证技巧分析
Mar 16 PHP
关于PHP中Session文件过多的问题及session文件保存位置
Mar 17 PHP
php 实现进制相互转换
Apr 07 PHP
php使用GD2绘制几何图形示例
Feb 15 PHP
PHP实现的简单留言板功能示例【基于thinkPHP框架】
Dec 07 PHP
Laravel框架实现文件上传的方法分析
Sep 29 PHP
tp5递归 无限级分类详解
Oct 18 PHP
php实现统计IP数及在线人数的示例代码
Jul 22 PHP
PHP curl批处理及多请求并发实现方法分析
Aug 15 #PHP
php使用curl_init()和curl_multi_init()多线程的速度比较详解
Aug 15 #PHP
php使用curl获取header检测开启GZip压缩的方法
Aug 15 #PHP
深入研究PHP中的preg_replace和代码执行
Aug 15 #PHP
PHP中一个有趣的preg_replace函数详解
Aug 15 #PHP
PHP使用curl_multi_select解决curl_multi网页假死问题的方法
Aug 15 #PHP
php+croppic.js实现剪切上传图片功能
Aug 14 #PHP
You might like
用PHP控制用户的浏览器--ob*函数的使用说明
2007/03/16 PHP
php SQL之where语句生成器
2009/03/24 PHP
深入PHP curl参数的详解
2013/06/17 PHP
jQuery TextBox自动完成条
2009/07/22 Javascript
js鼠标左右键 键盘值小结
2010/06/11 Javascript
javascript中length属性的探索
2011/07/31 Javascript
JavaScript声明变量名的语法规则
2015/07/10 Javascript
jquery实现红色竖向多级向右展开的导航菜单效果
2015/08/31 Javascript
jquery UI Datepicker时间控件的使用方法(基础版)
2015/11/07 Javascript
JavaScript中利用各种循环进行遍历的方式总结
2015/11/10 Javascript
Window.Open打开窗体和if嵌套代码
2016/04/15 Javascript
react native带索引的城市列表组件的实例代码
2017/08/08 Javascript
angular-tree-component的使用详解
2018/07/30 Javascript
angularjs通过过滤器返回超链接的方法
2018/10/26 Javascript
vue组件间的参数传递实例详解
2019/04/26 Javascript
Taro UI框架开发小程序实现左滑喜欢右滑不喜欢效果的示例代码
2020/05/18 Javascript
微信小程序开发之获取用户手机号码(php接口解密)
2020/05/17 Javascript
python使用PyCharm进行远程开发和调试
2017/11/02 Python
详解用TensorFlow实现逻辑回归算法
2018/05/02 Python
python生成密码字典的方法
2018/07/06 Python
python实现彩色图转换成灰度图
2019/01/15 Python
Python实现二叉树的常见遍历操作总结【7种方法】
2019/03/06 Python
Django通过dwebsocket实现websocket的例子
2019/11/15 Python
PyTorch在Windows环境搭建的方法步骤
2020/05/12 Python
如何利用Python识别图片中的文字
2020/05/31 Python
如何利用python之wxpy模块玩转微信
2020/08/17 Python
一款超酷的js+css3实现的3D标签云特效兼容ie7/8/9
2013/11/18 HTML / CSS
AHAVA美国官方网站:死海海泥护肤品牌
2016/10/18 全球购物
JD Sports比利时官网:英国领先的运动鞋和运动服饰零售商
2018/10/10 全球购物
德国拖鞋网站:German Slippers
2019/11/08 全球购物
日本最大的购物网站:日本乐天市场(Rakuten Ichiba)
2020/11/04 全球购物
红领巾广播站广播稿
2014/02/01 职场文书
民主评议党员自我评价材料
2014/09/18 职场文书
总经理岗位职责范本
2015/04/01 职场文书
青年岗位能手事迹材料(2016推荐版)
2016/03/01 职场文书
基于Python实现流星雨效果的绘制
2022/03/18 Python