将大量数据百万级导出到csv。由于数据量大,仅扩大内存仍会报错。
百万级的数据从数据库中查询,若不分段查或不刷新缓冲区,均会出错。
分段从数据库中查询再定期刷新缓冲区的方法。
set_time_limit(0);//让程序一直运行 ini_set('memory_limit', '128M');//设置临时内存 $fileName = '测试导出数据';//导出文件名 header('Content-Encoding: UTF-8'); header("Content-type:application/vnd.ms-excel;charset=UTF-8"); header('Content-Disposition: attachment;filename="' . $fileName . '.csv"'); $fp = fopen('php://output', 'a'); fwrite($fp, chr(0xEF).chr(0xBB).chr(0xBF));//bom防乱码 fputcsv($fp, ['title1', 'title2', 'title3']);//表头 require_once '../class/db.class.php'; $obj=new db(); $sqlBefore="select id from setting_item where 1 "; $count=$obj->getNumRow($sqlBefore); $nums=10000;//每次导出数量 $step=ceil($count/$nums);//循环次数 for($i = 0; $i < $step; $i++) { $start = $i * 10000; $sql=str_replace("id", "*", $sqlBefore)." LIMIT {$start},{$nums}"; //echo $sql; $q=$obj->getAll3($sql); while($item=$q->fetch_array(MYSQLI_USE_RESULT)){ //print_r($item); fputcsv($fp, $item); } //每1万条数据就刷新缓冲区 ob_flush(); flush(); }//for
13万条数据,导出时间7s。
默认不是文本,如001会被存在1,6/7会被保存成6月7日等,解决方案是统一保存成文本格式,导出变量加\t,如下:
$item["size"]="\t".$item["size"];