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 相关文章推荐
Discuz!下Memcache缓存实现方法
May 28 PHP
php excel reader读取excel内容存入数据库实现代码
Dec 06 PHP
php ci框架验证码实例分析
Jun 26 PHP
改写函数实现PHP二维/三维数组转字符串
Sep 13 PHP
将CMYK颜色值和RGB颜色相互转换的PHP代码
Jul 28 PHP
PHP_SELF,SCRIPT_NAME,REQUEST_URI区别
Dec 24 PHP
PHP is_array() 检测变量是否是数组的实现方法
Jun 13 PHP
PHP编程之设置apache虚拟目录
Jul 08 PHP
WordPress过滤垃圾评论的几种主要方法小结
Jul 11 PHP
通过修改Laravel Auth使用salt和password进行认证用户详解
Aug 17 PHP
PHP实现权限管理功能示例
Sep 22 PHP
PHP解析url并得到url参数方法总结
Oct 11 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
基于MySQL体系结构的分析
2013/05/02 PHP
Server.HTMLEncode让代码在页面里显示为源代码
2013/12/08 PHP
100行PHP代码实现socks5代理服务器
2016/04/28 PHP
php readfile()修改文件上传大小设置
2017/08/11 PHP
Laravel核心解读之异常处理的实践过程
2019/02/24 PHP
javascript延时重复执行函数 lLoopRun.js
2007/06/29 Javascript
JQuery FlexiGrid的asp.net完美解决方案 dotNetFlexGrid-.Net原生的异步表格控件
2010/09/12 Javascript
JS验证控制输入中英文字节长度(input、textarea等)具体实例
2013/06/21 Javascript
JavaScript省市联动实现代码
2014/02/15 Javascript
javascript设计模式之中介者模式Mediator
2014/12/30 Javascript
理解javascript定时器中的单线程
2016/02/23 Javascript
基于JQuery的$.ajax方法进行异步请求导致页面闪烁的解决办法
2016/05/10 Javascript
js实现文字列表无缝滚动效果
2017/06/23 Javascript
vue 系列——vue2-webpack2框架搭建踩坑之路
2017/12/22 Javascript
Angular实现可删除并计算总金额的购物车功能示例
2017/12/26 Javascript
vue项目引入Iconfont图标库的教程图解
2018/10/24 Javascript
React Component存在的几种形式详解
2018/11/06 Javascript
Vue使用axios出现options请求方法
2019/05/30 Javascript
详解Nuxt.js中使用Element-UI填坑
2019/09/06 Javascript
vue移动端使用appClound拉起支付宝支付的实现方法
2019/11/21 Javascript
Python实现高效求解素数代码实例
2015/06/30 Python
用python简单实现mysql数据同步到ElasticSearch的教程
2018/05/30 Python
Sanic框架应用部署方法详解
2018/07/18 Python
python 返回列表中某个值的索引方法
2018/11/07 Python
学习python的前途 python挣钱
2019/02/27 Python
Django 请求Request的具体使用方法
2019/11/11 Python
selenium 多窗口切换的实现(windows)
2020/01/18 Python
Python Merge函数原理及用法解析
2020/09/16 Python
python获取命令行参数实例方法讲解
2020/11/02 Python
轻化专业学生实习自我鉴定
2013/09/20 职场文书
夏季奶茶店创业计划书
2014/01/16 职场文书
2014新课程改革心得体会
2014/03/10 职场文书
学生请假条格式
2014/04/11 职场文书
纪念9.18事变演讲稿
2014/09/14 职场文书
中学生打架检讨书
2014/10/13 职场文书
经典法律座右铭(50句)
2019/08/15 职场文书