Laravel 大数据量分块处理
chunk() 的用法
有时,我们可能会一次性查出很大的结果集(上万条记录),这样就很可能导致内存溢出。
Laravel 框架的 chunk() 方法,可以将数据分块,每次只查询指定数量的数据块,交给回调函数处理。从而在处理大量数据集合时,能够有效减少内存消耗。
User::where('status', 0)->chunk(100, function ($users) {foreach ($users as $user) {$user->update(['name' => 'jack']);}
});
其实,chunk() 方法就是分页获取数据块。
chunk() 的注意事项
如果 chunk() 方法的回调函数,内部有自更新,影响到了原始查询条件的记录总数,就会出现遗漏数据的情况。
比如,将上面的
$user->update(['name' => 'jack']);
更改为
$user->update(['status' => 1]);
其实,原因很简单,因为 chunk() 每次分块(分页)都会对原始数据进行重新查询。如果原始数据变了,就可能会影响到分页的偏移。
错误示例:
// 获取待处理的记录
$res = DB::connection('mysql_pms')->table('pms_product_app_map as m')->selectRaw('m.*')->leftJoin('pms_product_push_record as r', function ($join) {$join->on('r.app_id', '=', 'm.app_id')->on('r.product_code', '=', 'm.product_code');})->whereNull('r.id') // 过滤掉已经推送成功的商品->orderBy('m.id', 'asc');$count = $res->count(); // 记录总数
$count_success = []; // 成功的记录$res->chunk(100, function ($records) use(&$count_success) {foreach ($records as $record) {try {// todo// 推送成功// 记录推送成功的记录$data = ['product_id' => $record->product_id,'updated_at' => Carbon::now()->toDateTimeString()];DB::connection('mysql_pms')->table('pms_product_push_record')->updateOrInsert(['app_id'=>$record->app_id, 'product_code'=>$record->product_code], $data);$count_success[] = $record->id;} catch (\Exception $e) {// todo}}
});
因此,如果 chunk() 方法的回调函数内部有自更新,影响了记录总数,就不要使用 chunk() 方法。
这时,推荐使用 cursor() 方法。
cursor() 的用法
cursor() 方法,使用游标迭代处理数据库记录,一次只执行单个查询,在处理大批量数据时,cursor() 方法可大幅减少内存的消耗。
foreach (Flight::where('foo', 'bar')->cursor() as $flight) {//
}
现在,我们使用 cursor() 游标重写上面的 chunk() 错误示例。
// 获取待处理的记录
$res = DB::connection('mysql_pms')->table('pms_product_app_map as m')->selectRaw('m.*')->leftJoin('pms_product_push_record as r', function ($join) {$join->on('r.app_id', '=', 'm.app_id')->on('r.product_code', '=', 'm.product_code');})->whereNull('r.id') // 过滤掉已经推送成功的商品->orderBy('m.id', 'asc');$count = $res->count(); // 记录总数
$count_success = []; // 成功的记录foreach ($res->cursor() as $record) {try {// todo// 推送成功// 记录推送成功的记录$data = ['product_id' => $record->product_id,'updated_at' => Carbon::now()->toDateTimeString()];DB::connection('mysql_pms')->table('pms_product_push_record')->updateOrInsert(['app_id'=>$record->app_id, 'product_code'=>$record->product_code], $data);$count_success[] = $record->id;} catch (\Exception $e) {// todo}
}
Laravel 大数据量分块处理相关推荐
- Laravel 使用PHP_XLSXWriter实现大数据量Excel导出
我在去年写过一篇关于laravel的Excel导出文章:Laravel Excel 实现 Excel/CSV 文件导入导出功能,使用的是Laravel Excel实现的. 该扩展包含Excel导入导出 ...
- 数据库大数据量、高并发、高可用解决方案!
数据库性能瓶颈 对于一些互联网项目来说,企业为节省成本,一般会考虑将所有的数据都存储在一个数据库中,这个时候我们只需要考虑数据库优化.SQL优化.数据缓存.限流,消息队列.服务器性能等问题. 阿里巴巴 ...
- 大数据量高并发的数据库优化(转载)
对其进行处理是一项艰巨而复杂的任务.原因有以下几个方面: 一.数据量过大,数据中什么情况都可能存在.如果说有10条数据,那么大不了每条去逐一检查,人为处理,如果有上百条数据,也可以考虑,如果数据上到千 ...
- 3DGIS第二章 大数据量场景加速绘制基本原理与方法
对于仅有几百个多边形和几十兆的低分辨率纹理简单场景,在现阶段一般配置的计算机上也很容易达到实时仿真的目标.然而,随着场景规模的增大,大规模虚拟场景中往往包含上万个多边形,甚至多达几百万个多边形和几百兆 ...
- 大数据量场景加速绘制基本原理与方法
对于仅有几百个多边形和几十兆的低分辨率纹理简单场景,在现阶段一般配置的计算机上也很容易达到实时仿真的目标.然而,随着场景规模的增大,大规模虚拟场景中往往包含上万个多边形,甚至多达几百万个多边形和几百兆 ...
- 第二章 大数据量场景加速绘制基本原理与方法
对于仅有几百个多边形和几十兆的低分辨率纹理简单场景,在现阶段一般配置的计算机上也很容易达到实时仿真的目标.然而,随着场景规模的增大,大规模虚拟场景中往往包含上万个多边形,甚至多达几百万个多边形和几百兆 ...
- 大数据导出excel大小限制_EXCEL大数据量导出的解决方案
将web页面上显示的报表导出到excel文件里是一种很常见的需求.润乾报表的类excel模型,支持excel文件数据无失真的导入导出,使用起来非常的方便.然而,当数据量较大的情况下,excel本身的支 ...
- spring Batch实现数据库大数据量读写
spring Batch实现数据库大数据量读写 博客分类: spring springBatchquartz定时调度批处理 1. data-source-context.xml Xml代码 &l ...
- 1.3.8 excel for mysql_实时生成并下载大数据量的EXCEL文件,用PHP如何实现
有一个这样的需求,通过选择的时间段导出对应的用户访问日志到excel中, 由于用户量较大,经常会有导出50万加数据的情况.而常用的PHPexcel包需要把所有数据拿到后才能生成excel, 在面对生成 ...
最新文章
- android系统应用程序,Android系统应用程序基本概念解读
- UIScrollView 的代理方法简单注解
- echo count(“abc”); 输出什么?
- 关于mysql启动错误
- CRM_REPORT_RF_AUTH_OBJ_ORD_LP
- ES6新语法--解构赋值
- 数据分析【实践】——AB测试的应用、案例及关键点
- 我不建议大家随便跳槽
- iframe 跳转到其他页面
- CAN总线(一)——CAN总线是什么,在哪用,怎么用?
- leetcodeOj:66. Plus One
- 瑞吉外卖(27)-查看购物车信息、清空购物车功能开发
- 【图像超分辨率重建】——GRL论文精读笔记
- 在windows7下农业银行网银(金e顺)不能使用
- 百度云(主机管理密码、FTP登录密码、MySQL账号密码)配置 - 入口篇
- 计算机技术交流群QQ:69706169,电脑维护故障排除,网络,通信,交换,电子等欢迎加入!...
- Vue生命周期 (图解+代码解析)
- Python综合案例2(险种缴费记录管理)
- python与炒股_Python量化炒股入门与实战技巧
- 数据治理解决方案概述