PHP百万级数据导出解决方案

3 篇文章 0 订阅
2 篇文章 0 订阅

PHP百万级数据导出解决方案

背景:

公司需要将一批海量数据导出给用户,数据来源于数据库,且数据条数在百万级以上未来可能更多。

分析:

1、使用EXCEL格式导出

如果使用excel文件导出目前PHP支持的库有 phpoffice/phpspreadsheet 目前也是start比较多的,让我来分析一下他的优缺点。

优点:使用简单,容易上手
缺点:很消耗内存,导出的数据量越大消耗的内存也越大当然导出的时间也越大,而且excel行数是有限制的

2、使用CSV格式导出

相比前者csv格式在导出大数据方面还是有决定的优势,这里我们使用的是laravel的组件库league/csv
优点:在大数据导出方面消耗内存小
缺点:数据不是特别的直观

解决方案:

由于这个业务场景下的数据无法预估到底会产生多少数据,可能百万,可能千万那么我采用了csv的方案。但是csv的方案也会存在 时间问题,如果数据越大客户端等待的时间也就越大。当然这个无论是方案excel方法还是csv都会遇到这个问题。如果是平常的http协议肯定是会连接响应超时的,这里我采用的websocket方法传输,使用websocket方法是比较合适的同时也可以实时获取导出状态。

/**
 * 这里用的是hyperf框架但是这个ORM还是用的laravel的底层
 **/
 
//从数据库读取对应的数据
 public function getData($i, $limit)
    {
        for ($n = 1; $n <= $i; ++$n) {
            $logs = Db::table('call_log')->select(['call_no', 'called_no', 'ring', 'agent', 'call_time_length'])->paginate($limit, ['call_no', 'call_time_length'], '', $n)->items();
            $logs = json_decode(json_encode($logs), true); //将结果集转为数组类型
            yield $logs;  //借助生成器完成分页查询
        }
    }


//这个为主方法
 public function index()
    {
        $starttime = explode(' ', microtime());  //记录程序执行前的时间
        $a = memory_get_usage(); 				//记录程序执行前所用的内存
        $count = $this->dataCount(); 			//先查出有多少条数据
        echo PHP_EOL . '总数据条数:' . $count . PHP_EOL;
        $count = (int)ceil($count / 100000); //设置limit大小类似分页查询 limit越小等待时间越长,消耗的内存越小 100000表示每次查询100000条数据写入
        $head = ['主叫', '被叫', '响铃时间', '坐席', '通话时长(秒)']; 
        $csv = Writer::createFromPath("public/".time().".csv", 'w+'); //写入文件
        $res = $this->getData($count, 100000);  
        $csv->insertOne($head);
        foreach ($res as $values) {
             $csv->insertAll($values);
             $b = memory_get_usage();
        	 echo '总消耗内存' . sprintf('%.3f', ($b - $a) / (1024 * 1024)) . 'M' . PHP_EOL;
        }
        $endtime = explode(' ', microtime());
        $thistime = $endtime[0] + $endtime[1] - ($starttime[0] + $starttime[1]);
        $thistime = round($thistime, 3);
        echo "本网页执行耗时:" . $thistime . " 秒。" . PHP_EOL;
        return 1;
    }

【程序运行图】

在这里插入图片描述

导出一百万条数据用了两分钟左右的时间,但是内存消耗只消耗了77M当然你可以降低分页条数来进一步降低内存的消耗。实验中我用的是10万数据,你可以更低但是所消耗的时间也会越长,这个就像软件工程里讲的一样为了提升效率要么牺牲空间提高时间,要么牺牲时间降低空间。

总结:EXCEL和CSV各有各的优点,关键是自己看看使用的业务场景,如果说是对于少量数据的导出1-2W之间可以使用excel导出如果是对未来的数据无法预估那还是建议使用csv的方案,因为当数据不断增加时如果采用的是方案一excel导出不仅对服务器配置要高同时excel自身也存在限制。
  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值