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 和 MySQL 基础教程(四)
Oct 09 PHP
php 无限级 SelectTree 类
May 19 PHP
php iconv() : Detected an illegal character in input string
Dec 05 PHP
PHP判断搜索引擎蜘蛛并自动记忆到文件的代码
Feb 04 PHP
yii上传文件或图片实例
Apr 01 PHP
PHP采用curl模仿用户登陆新浪微博发微博的方法
Nov 07 PHP
深入浅出php socket编程
May 13 PHP
使用PHP编写发红包程序
Jul 22 PHP
PHP响应post请求上传文件的方法
Dec 17 PHP
Laravel最佳分割路由文件(routes.php)的方式
Aug 04 PHP
PHP消息队列实现及应用详解【队列处理订单系统和配送系统】
May 20 PHP
Yii实现微信公众号场景二维码的方法实例
Aug 30 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 一个比较完善的简单文件上传
2010/03/25 PHP
php抽奖小程序的实现代码
2013/06/18 PHP
Javascript MD4
2006/12/20 Javascript
jquery动画2.元素坐标动画效果(创建一个图片走廊)
2012/08/24 Javascript
uploadify在Firefox下丢失session问题的解决方法
2013/08/07 Javascript
windows下安装nodejs及框架express
2015/08/07 NodeJs
JS闭包、作用域链、垃圾回收、内存泄露相关知识小结
2016/05/16 Javascript
基于javascript实现表格的简单操作
2016/05/21 Javascript
浅谈js函数的多种定义方法与区别
2016/11/29 Javascript
Vue利用路由钩子token过期后跳转到登录页的实例
2017/10/26 Javascript
React Native中导航组件react-navigation跨tab路由处理详解
2017/10/31 Javascript
浅析JS抽象工厂模式
2017/12/14 Javascript
vue项目动态设置页面title及是否缓存页面的问题
2018/11/08 Javascript
Vue form表单动态添加组件实战案例
2019/09/02 Javascript
JavaScript监听触摸事件代码实例
2019/12/30 Javascript
[04:07]显微镜下的DOTA2第八期——英雄复活动作
2014/06/24 DOTA
python二叉树遍历的实现方法
2013/11/21 Python
Python中函数的多种格式和使用实例及小技巧
2015/04/13 Python
使用python将大量数据导出到Excel中的小技巧分享
2018/06/14 Python
Flask核心机制之上下文源码剖析
2018/12/25 Python
python多继承(钻石继承)问题和解决方法简单示例
2019/10/21 Python
Python序列化pickle模块使用详解
2020/03/05 Python
使用anaconda安装pytorch的实现步骤
2020/09/03 Python
python 实现简易的记事本
2020/11/30 Python
CSS3中border-radius属性设定圆角的使用技巧
2016/05/10 HTML / CSS
柯基袜:Corgi Socks
2017/01/26 全球购物
Veronica Beard官网:在酷、经典和别致之间找到了平衡
2018/01/11 全球购物
银行求职信个人范文
2013/12/16 职场文书
摄影专业毕业生求职信
2014/03/13 职场文书
报告会主持词
2014/04/02 职场文书
初中优秀班集体申报材料
2014/05/01 职场文书
支行行长竞聘报告
2014/11/06 职场文书
个人委托函范文
2015/01/29 职场文书
小学生大队委竞选稿
2015/11/20 职场文书
导游词之峨眉乐山/兵马俑/北京故宫御花园
2019/09/03 职场文书
Pandas||过滤缺失数据||pd.dropna()函数的用法说明
2021/05/14 Python