php 导出 大文件,php导出超大csv导出方法,读取超大文件或者接受超大数组,防止内存溢出...

该博客讨论了在PHP环境中处理大量数据的策略,通过分割数据成小块进行查询和写入CSV,以避免内存溢出。作者推荐每30000条数据为一组,实现了在30秒内处理52万多条记录。此外,还对比了使用迭代器的懒人方法,虽然速度较慢但能有效防止内存溢出。文中提供了示例代码,并提出了在Windows 32位系统上可能的优化方案,对于64位系统和更大文件处理,可以考虑使用压缩和迭代器按行读取。
摘要由CSDN通过智能技术生成

基本思路就是,知道总数之后分割成2万一个数组进行查询,最后独立写入csv,避免数据过大导致溢出

速度还不错,在php7下,机器I5 8G内存,128G,SSD,52W多条,大概也就30秒,出来整个文件38.2M

$per = 10000; 37秒

$per = 20000; 34秒

$per = 30000; 的时候速度最快29秒左右

$per = 40000;30-31秒

所以建议在30000步幅,比较好,我的环境是windows 32位,64位或许会更好

建议导入文件过多就zip压缩之后再下载

laravel 写的demo  2018年6月19日18:13:26

$start = time();set_time_limit(0);ini_set('memory_limit', '512M');//获取总数

$count = DataChinaYearData::count();//526672

$per = 30000;$section = array();for ($i = 0; $i <= $count; $i += $per) {$section[] = $i;

}if (end($section) < $count) {$section[] = $count;

}//清理输出流的防止乱码

ob_flush();flush();$fp = fopen('file.csv', 'w');foreach ($section as $k => $v) {$list = array();$list = DataChinaYearData::offset($v)->limit($per)->get()->toArray();foreach ($list as $fields) {

fputcsv($fp, $fields);

}unset($list); //防止溢出

ob_flush();flush();

}fclose($fp);$end = time();$time = $end - $start;echo $time . '秒';

另一种懒人写法,全部使用迭代器去操作

$start = time();set_time_limit(0);

$fp = fopen('file.csv', 'w');foreach (new \ArrayObject(DataChinaYearData::get()->toarray()) as $k => $v) {

fputcsv($fp, $v);

}fclose($fp);$end = time();$time = $end - $start;echo $time . '秒';

原理也很简单,pdo就是迭代器,直接使用数组迭代器赋值,不使用变量接收就不会内存溢出

测试了2次,39秒和40秒,显然这样的速度就慢了一些,可以通过逻辑优化的就使用逻辑优化,纯靠语言特性优化有时候是方便了写代码但是代码思维逻辑就差多了

也可以通过使用迭代器接受超大数组,比如我需要读取一个2G或者更大的文本文件或者excel,我直接按行读取,然后全部放入迭代器中这样不会出现内存溢出的情况

伪demo,有时间在写个实际的demo

public static functiontest() {

pp(self::get_array() instanceof \Generator);

pp(self::get_array());/** Generator Object

(

)

**/

foreach (self::get_array() as $k => $v) {

p($k);

p($v);

}

}public static functionget_array() {$rr = array('0' => array('a' => 'aa'), '1' => array('a' => 'bb'), '2' => array('c' => 'cc'), '3' => array('d' => 'dd'));//$rr = array('0' => 'a', '1' => 'b', '2' => 'c', '3' => 'd');

foreach ($rr as $k => $v) {

yield$k => $v;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值