本文共 2560 字,大约阅读时间需要 8 分钟。
近年来,公司项目中经常需要处理大数据的导出需求。虽然之前开发过几次导出功能,但面对数据量较大的挑战时,发现了不少坑。现将这些经验总结如下:
在处理大数据导出时,PHP的环境配置需要特别注意:
执行时间限制:默认情况下,PHP脚本执行时间限制为30秒。若数据量较大(如百万级别),30秒往往不够用。建议在脚本开头添加 set_time_limit(0),以避免因超时而中断。
内存限制:PHP的默认内存限制为128M。虽然可以通过修改 memory_limit 来提升,但这在实际服务器环境中往往不太现实。建议谨慎使用,避免因内存过大占用而引发问题。
在选择Excel作为导出格式时,需注意以下限制:
单表数据限制:Excel 2007-2010版本支持的单表最大数据量为1048576行,16384列。因此,若一次性导入一张表的数据超过该限制,会导致内存溢出。
PHPExcel内存问题:使用 fputcsv 导入大数据时,PHPExcel会将数据缓存到一个变量中,容易引发内存溢出。解决方案是通过分批导入和使用 PHPExcel_Settings::setCacheStorageMethod 更改缓冲方式。
虽然CSV文件格式在一定程度上克服了Excel的数据量限制,但仍需注意以下问题:
输出缓存问题:使用 putcsv 函数进行大数据输出时,输出缓存可能过大,导致错误。需定期通过 ob_flush() 和 flush() 刷新缓存。
分割文件:由于CSV文件没有Excel的数据量限制,直接导入可能导致内存溢出。建议将数据分割成多个CSV文件,避免一次性处理过多数据。
针对大数据导出的具体场景,建议采取以下优化措施:
分批处理数据:从数据库中分批读取数据,以防止变量内存溢出。
选择合适的文件格式:采用CSV文件格式导出,既支持大数据量,又方便后续处理和查看。
分割文件保存:为了避免Excel或其他工具读取时的数据量限制,建议将数据分割成多个CSV文件保存。
文件压缩下载:为了提供更友好的用户体验,建议将多个CSV文件压缩成ZIP格式,方便用户下载并解压。
以下是一个实现大数据导出的PHP脚本示例:
function putCsv(array $head, $data, $mark = 'attack_ip_info', $fileName = "test.csv"){ set_time_limit(0); $sqlCount = $data->count(); header('Content-Type: application/vnd.ms-excel;charset=utf-8'); header('Content-Disposition: attachment;filename="' . $fileName . '"'); header('Cache-Control: max-age=0'); $sqlLimit = 100000; $limit = 100000; $cnt = 0; $fileNameArr = array(); for ($i = 0; $i < ceil($sqlCount / $sqlLimit); $i++) { $fp = fopen($mark . '_' . $i . '.csv', 'w'); fputcsv($fp, $head); $dataArr = $data->offset($i * $sqlLimit)->limit($sqlLimit)->get()->toArray(); foreach ($dataArr as $a) { $cnt++; if ($limit == $cnt) { ob_flush(); flush(); $cnt = 0; } fputcsv($fp, $a); } fclose($fp); } $zip = new ZipArchive(); $filename = $mark . ".zip"; $zip->open($filename, ZipArchive::CREATE); foreach ($fileNameArr as $file) { $zip->addFile($file, basename($file)); } $zip->close(); foreach ($fileNameArr as $file) { unlink($file); } header("Cache-Control: max-age=0"); header("Content-Description: File Transfer"); header('Content-disposition: attachment; filename=' . basename($filename)); header("Content-Type: application/zip"); header("Content-Transfer-Encoding: binary"); @readfile($filename); unlink($filename);} 以上内容仍有优化空间,例如可以通过异常捕获机制处理临时文件删除问题,或通过生成多个工作表的方式优化文件格式。希望以上实践经验能为开发提供参考,欢迎随时交流心得!
转载地址:http://ohvfk.baihongyu.com/