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 smarty模版引擎中的缓存应用
Dec 11 PHP
PHP中基本符号及使用方法
Mar 23 PHP
PHP 可阅读随机字符串代码
May 26 PHP
PHP下使用CURL方式POST数据至API接口的代码
Feb 14 PHP
基于python发送邮件的乱码问题的解决办法
Apr 25 PHP
解决php表单重复提交实现方法
Sep 29 PHP
在Yii2中使用Pjax导致Yii2内联脚本载入失败的原因分析
Mar 06 PHP
PHP常见错误提示含义解释(实用!值得收藏)
Apr 25 PHP
PHP通过引用传递参数用法分析
Dec 01 PHP
php实现xml转换数组的方法示例
Feb 03 PHP
如何用PHP实现多线程编程
May 26 PHP
浅谈PHP7中的一些小技巧
May 29 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
Discuz 模板引擎的封装类代码
2008/07/18 PHP
用JavaScript和注册表脚本实现右键收藏Web页选中文本
2007/01/28 Javascript
简明json介绍
2008/09/28 Javascript
JavaScript Event学习补遗 addEventSimple
2010/02/11 Javascript
js移除事件 js绑定事件实例应用
2012/11/28 Javascript
当鼠标移动时出现特效的JQuery代码
2013/11/08 Javascript
用javascript读取xml文件读取节点数据
2014/08/12 Javascript
js使用cookie记录用户名的方法
2015/11/26 Javascript
Bootstrap富文本组件wysiwyg数据保存到mysql的方法
2016/05/09 Javascript
原生js仿jquery一些常用方法(必看篇)
2016/09/20 Javascript
微信小程序 animation API详解及实例代码
2016/10/08 Javascript
js实现右键菜单功能
2016/11/28 Javascript
JS实现给json数组动态赋值的方法示例
2020/03/19 Javascript
JS控制鼠标拒绝点击某一按钮的实例
2017/12/29 Javascript
javascript动态创建对象的属性详解
2018/11/07 Javascript
[02:32]DOTA2亚洲邀请赛 C9战队出场宣传片
2015/02/07 DOTA
Python切片知识解析
2016/03/06 Python
python 内置函数filter
2017/06/01 Python
python selenium 对浏览器标签页进行关闭和切换的方法
2018/05/21 Python
python中的协程深入理解
2019/06/10 Python
Python:合并两个numpy矩阵的实现
2019/12/02 Python
Python-openCV读RGB通道图实例
2020/01/17 Python
pycharm 设置项目的根目录教程
2020/02/12 Python
python中os包的用法
2020/06/01 Python
Python中zipfile压缩文件模块的基本使用教程
2020/06/14 Python
Python字符串函数strip()原理及用法详解
2020/07/23 Python
python获得命令行输入的参数的两种方式
2020/11/02 Python
详解通过变换矩阵实现canvas的缩放功能
2019/01/14 HTML / CSS
一夜的工作教学反思
2014/02/08 职场文书
原料仓仓管员岗位职责
2014/07/08 职场文书
网络工程专业大学生求职信
2014/10/01 职场文书
后天观后感
2015/06/08 职场文书
圣诞晚会主持词
2015/07/01 职场文书
缓存替换策略及应用(以Redis、InnoDB为例)
2021/07/25 Redis
Python爬虫网络请求之代理服务器和动态Cookies
2022/04/12 Python
Python FuzzyWuzzy实现模糊匹配
2022/04/28 Python