解决csv导出百万数据超时问题

前提条件

准备好测试的100W条数据

set_time_limit(0);
$num = 1000000;
$pageCount = ceil($num/5000);
for ($i=0; $i<$pageCount; $i++){
    $str = "";
    for ($j=$i*5000; $j<($i+1)*5000; $j++){
        $tmp = "测试";
        $tmp .= $i*5000+$j;
        $str .= "('".$tmp."','".date('Y-m-d H:i:s',time())."'),";
    }
    $insertSql = 'insert into qxl_test (name,time) values'.rtrim($str,',');
    M()->execute($insertSql);
}

上面就是造出来的10w测试数据


为了有更好的效果对比吧两种方法都放出来 

之前简单的一种

set_time_limit(0);
$filename = '文件名'.date('Y-m-d H:i:s').'.csv';
header('Content-Type: application/octet-stream');
header("Content-Disposition: attachment; filename=\"" . $filename."\"");
echo iconv("UTF-8", "gb2312", "ID,姓名,时间 \t\n");
$data = M("test")->select();
foreach ($data as $key => $val) {
    $temp[] = $val['id'];
    $temp[] = $val['name'];
    $temp[] = $val['time'];
    echo iconv("UTF-8", "gb2312", implode(',',$temp)."\t\n");
    unset($temp);//资源释放
}

效果图

拾染博客

优化后的方法

ini_set('memory_limit','1024M'); //设置程序运行的内存
ini_set('max_execution_time',0); //设置程序的执行时间,0为无上限
ob_end_clean();  //清除内存
ob_start();  //使用ob_start()输出到缓冲区,而不是到浏览器
header("Content-Type: text/csv");
$fileName = "文件名".time();
header("Content-Disposition:filename=".$fileName.'.csv');
$fp=fopen('php://output','w'); //php语言中一个只写的数据流,写入到输出缓冲区
fwrite($fp, chr(0xEF).chr(0xBB).chr(0xBF)); //把内容写入文件指针$fp出 //chr(0xEF).chr(0xBB).chr(0xBF)防止乱码
$headArr = array("序号","姓名","时间"); //标题
fputcsv($fp,$headArr); //函数将行格式化为csv并写入一个打开的文件
$index = 0;
$data = M("test")->select();//数据源
foreach ($data as $item) {
    if($index==1000){ //每次写入1000条数据清除内存
        $index=0;
        ob_flush();//清除内存 ob_flush/flush使用顺序
        flush();
    }
    $index++;
    fputcsv($fp,$item); //函数将行格式化为csv并写入一个打开的文件
}

ob_flush();
flush();
ob_end_clean();//清除内存
exit();

效果图

拾染博客

上面的方法是自己在网上查找的,代码的注释是自己敲的希望可以帮助到看到的有缘人,加油

拾染博客
请先登录后发表评论
  • 最新评论
  • 总共0条评论