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 相关文章推荐
理解PHP5中static和const关键字的区别
Mar 19 PHP
php数组的概述及分类与声明代码演示
Feb 26 PHP
phpmailer在服务器上不能正常发送邮件的解决办法
Jul 08 PHP
CodeIgniter采用config控制的多语言实现根据浏览器语言自动转换功能
Jul 18 PHP
PHP+FastCGI+Nginx配置PHP运行环境
Aug 07 PHP
PHP图片处理之图片背景、画布操作
Nov 19 PHP
php实现redis数据库指定库号迁移的方法
Jan 14 PHP
php字符串分割函数用法实例
Mar 17 PHP
php实现的任意进制互转类分享
Jul 07 PHP
YII框架实现自定义第三方扩展操作示例
Apr 26 PHP
Thinkphp自定义生成缩略图尺寸的方法
Aug 05 PHP
详解Laravel设置多态关系模型别名的方式
Oct 17 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
AMFPHP php远程调用(RPC, Remote Procedure Call)工具 快速入门教程
2010/05/10 PHP
destoon文章模块调用企业会员资料的方法
2014/08/22 PHP
PHP正则匹配到2个字符串之间的内容方法
2018/12/24 PHP
php服务器的系统详解
2019/10/12 PHP
IE 条件注释详解总结(附实例代码)
2009/08/29 Javascript
Jquery右下角抖动、浮动 实例代码(兼容ie6、FF)
2013/08/15 Javascript
JavaScript利用append添加元素报错的解决方法
2014/07/01 Javascript
浅谈Javascript如何实现匀速运动
2014/12/19 Javascript
浅谈angular懒加载的一些坑
2016/08/20 Javascript
微信小程序自定义导航隐藏和显示功能
2017/06/13 Javascript
ajax请求data遇到的问题分析
2018/01/18 Javascript
解决vue-cli + webpack 新建项目出错的问题
2018/03/20 Javascript
使用D3.js构建实时图形的示例代码
2018/08/28 Javascript
详解Vue2 添加对scss的支持
2019/01/02 Javascript
使用layui监听器监听select下拉框,事件绑定不成功的解决方法
2019/09/28 Javascript
微信小程序实现带放大效果的轮播图
2020/05/26 Javascript
node.js通过url读取文件
2020/10/16 Javascript
js正则表达式简单校验方法
2021/01/03 Javascript
[01:54]TI珍贵瞬间系列(五):压力
2020/08/29 DOTA
Python函数中*args和**kwargs来传递变长参数的用法
2016/01/26 Python
Python内置模块hashlib、hmac与uuid用法分析
2018/02/12 Python
Python selenium实现微博自动登录的示例代码
2018/05/16 Python
Python 数据可视化pyecharts的使用详解
2019/06/26 Python
浅谈ROC曲线的最佳阈值如何选取
2020/02/28 Python
Django+Celery实现动态配置定时任务的方法示例
2020/05/26 Python
Keras官方中文文档:性能评估Metrices详解
2020/06/15 Python
Sahajan美国:阿育吠陀护肤品牌
2021/01/09 全球购物
当我正在为表建立索引的时候,SQL Server 会禁止对表的访问吗
2014/04/28 面试题
户外亲子活动策划方案
2014/02/07 职场文书
元旦寄语大全
2014/04/10 职场文书
产品设计开发计划书
2014/05/07 职场文书
医生学习党的群众路线教育实践活动心得体会
2014/11/03 职场文书
2016大学生暑期三下乡心得体会
2016/01/23 职场文书
2019年手机市场的调研报告2篇
2019/10/10 职场文书
面试必问:圣杯布局和双飞翼布局的区别
2021/05/13 HTML / CSS
如何使用pdb进行Python调试
2021/06/30 Python