laravel实现大数据csv导出
首先说明几点:
- excel格式的文件最大支持100万的数据,所以不考虑使用excel格式
- laravel的toArray()方法有内存泄露,所以大量数据导出不能使用.
- 当然要使用chunk方法查询数据,然后写到文件中
关于toArray()方法内存泄露排查
chunk()方法的代码块如下(chunk中按理是不用unset的,会自动释放):
$ormQuery->chunk(1000, function ($data) use (&$firstWrite, $fp) {
Log::info("开始:".memory_get_usage());
$data = $data->toArray();
Log::info("结束:".memory_get_usage());
unset($data);
Log::info("usnet 结束:".memory_get_usage());
});
日志
从下往上看
Screen Shot 2017-04-01 at 4.16.38 PM.png
通过日志我们可以分析得出:
在将一个“组块”的 Eloquent 模型转为数组的时候$data = $data->toArray();内存增加了很多.最后unset的时候又没有释放回初始值.实际上chunk中是不需要unset释放的.
解决
使用DB::table("xxx")->->orderBy(xx)->chunk(xx);方式查询数据,查询结果在使用$data = json_decode(json_encode($data), true);转换成数组,每次chunk执行进去,内存都是一样的,内部也不需要unset.
大数据导出最后做的方案
因为数据量大,所以我的做法是,小量数据导出就直接发送给用户.大数据导出,走队列任务,然后做一个报表管理,用户可以查看进度和完成后下载.
在浏览器中直接返回文件和后台写入文件
函数基本使用
$fp = fopen("文件路径/文件名", "a"); //a表示追加模式
fwrite($fp, chr(0xEF).chr(0xBB).chr(0xBF)); // 添加 BOM,不然excel打开csv是乱码
在chunk的闭包中写数据: fputcsv($fp, $array);
fclose($fp);
在队列中导出
$fp = fopen(storage_path('app/public/exports')."/".$report->name, "a");
fwrite($fp, chr(0xEF).chr(0xBB).chr(0xBF)); // 添加 BOM
$firstWrite = true;
$query = $expoter->customQuery($query);
$query->orderBy($tableName.".id")->chunk(1000, function ($data) use (&$firstWrite, $fp, $expoter) {
$data = json_decode(json_encode($data), true);
$data = $expoter->customData($data);
//有一些列总是不导出,如icon,image,images
$data = ExportUtils::removeInvalids($data);
//写列名
if ($firstWrite) {
$columnNames = [];
//获取列名
foreach ($data[0] as $key => $value) {
$columnNames[] = admin_translate($key, "coupon");
}
fputcsv($fp, $columnNames);
$firstWrite = false;
}
foreach ($data as $item) {
fputcsv($fp, $item);
}
});
fclose($fp);
在浏览器中返回数据
$response = new StreamedResponse(null, 200, [
'Content-Type' => 'text/csv',
'Content-Disposition' => 'attachment; filename="'.$fileName.'"',
]);
$response->setCallback(function () use ($query, $tableName) {
$out = fopen('php://output', 'w');
fwrite($out, chr(0xEF).chr(0xBB).chr(0xBF)); // 添加 BOM
$firstWrite = true;
$query = $this->customQuery($query);
$query->orderBy($tableName.".id")->chunk(500, function ($data) use (&$firstWrite, $out) {
$data = json_decode(json_encode($data), true);
$data = $this->customData($data);
//有一些列总是不导出,如icon,image,images
$data = ExportUtils::removeInvalids($data);
//写列名
if ($firstWrite) {
$columnNames = [];
//获取列名
foreach ($data[0] as $key => $value) {
$columnNames[] = admin_translate($key, "coupon");
}
fputcsv($out, $columnNames);
$firstWrite = false;
}
foreach ($data as $item) {
fputcsv($out, $item);
}
});
fclose($out);
});
$response->send();
laravel实现大数据csv导出的更多相关文章
- php使用fputcsv进行大数据的导出
为了实验大数据的导出,我们这里先自已创建一张大表,表结构如下: CREATE TABLE `tb_users` ( `id` int(11) unsigned NOT NULL AUTO_INCREM ...
- PHPExcel 大数据的导出
PHPExcel 是一个php语言读取导出数据.导入生成Excel的类库,使用起来非常方便,但有时会遇到以些问题,比如导出的数据超时,内存溢出等. 下面我们来说说这些问题和解决办法. PHPExcel ...
- ajax大数据排队导出+进度条
描述 :我们现在有很多数据,分表存放,现在需要有精度条的导出.最后面有完整源码. 效果图:
- poi 操作Excel 以及大数据量导出
maven 依赖 (版本必须一致,否则使用SXSSFworkbook 时程序会报错) <dependency> <groupId>org.apache.poi</grou ...
- EasyPoi大数据导入导出百万级实例
EasyPoi介绍: 利用注解的方式简化了Excel.Word.PDF等格式的导入导出,而且是百万级数据的导入导出.EasyPoi官方网址:EasyPoi教程_V1.0 (mydoc.io).下面我写 ...
- SQL Server 使用bcp进行大数据量导出导入
转载:http://www.cnblogs.com/gaizai/archive/2010/04/17/1714389.html SQL Server的导出导入方式有: 在SQL Server中提供了 ...
- Export大数据量导出和打包
项目需求 导出生成大批量数据的文件,一个Excel中最多存有五十万条数据,查询多余五十万的数据写多个Excel中.导出完成是生成的多个Excel文件打包压缩成zip,而后更新导出记录中的压缩文件路 ...
- 使用内存映射文件MMF实现大数据量导出时的内存优化
前言 导出功能几乎是所有应用系统必不可少功能,今天我们来谈一谈,如何使用内存映射文件MMF进行内存优化,本文重点介绍使用方法,相关原理可以参考文末的连接 实现 我们以单次导出一个excel举例(csv ...
- 大数据Excel导出方案
static void Main(string[] args) { Excel.Application app = new Excel.Application(); Excel._Workbook r ...
- 记录一笔关于PHPEXCEL导出大数据超时和内存溢出的问题
通过查阅资料可以找到PHPEXCEL本身已经有通过缓存来处理大数据的导出了.但是昨晚一直没有成功,这可捉急了.最后想来想去就替换了phpExcel的版本了.最后就成功了.话不多说,代码附上 <? ...
随机推荐
- ajax json php post 方法
1.前端 <script type="text/javascript"> function LoadData(arg){ arg.dept=$("#DeptS ...
- jquery.axios
概念:通过 HTTP 请求加载远程数据. *注:所有的选项都可以通过$.ajaxSetup()函数来全局设置. 回调函数:要处理$.ajax()得到的数据,则需要使用回调函数.beforeSend.e ...
- SpringMVC配置文件applicationContext.xml头信息
applicationContext.xml头信息 <?xml version="1.0" encoding="UTF-8"?> <beans ...
- idea乱码
第一步:修改intellij idea配置文件: 找到intellij idea安装目录,bin文件夹下面idea64.exe.vmoptions和idea.exe.vmoptions这两个文件,分别 ...
- TiSpark 初级应用
目前正在使用tispark 进行离线计算,简单记录一下操作过程 一.技术验证 场景:计算每次充电过程中单体最高电压的变化速率 解决方案: 使用tispark 直接访问tidb的数据,采用sp ...
- MybatisPlus 实现多表联合分页条件查询
方式一:XML 有点繁琐,不太想用 mapper接口 public interface RoomMapper extends BaseMapper<Room> { List<Room ...
- 搭建简单nfs共享
1.查看是否安装nfs,rpcbind包 rpm -q nfs-utils rpm -q rpcbind 2.安装包 服务端和客户端 yum -y install nfs-utils 3.修改配置 ...
- MySQL视频学习 1-18小节
地址:https://www.bilibili.com/video/av39807944/?p=16 1-15:撘环境.建表.数据类型(https://www.runoob.com/mysql/mys ...
- JDK 7 HashMap 并发情况下的死锁问题
目录 问题描述 详细解释 问题描述 JDK7的 HashMap 解决冲突用的是链表,在插入链表的时候用的是头插法,每次在链表的头部插入新元素.resize() 的时候用的依然是头插,头插的话,如果某个 ...
- java.lang.StackOverflowError错误的解决方法
对于java.lang.StackOverflowError认识 如下图所示,报出来这种错误的话,很大概率是有以下几种原因: 现在来看一看我的报错界面: 不难看出,这是无限循环的那种情况,所以,我就去 ...