如何优化使用PHP导出MySQL数据库的速度
MySQL导出函数优化方案
核心性能瓶颈(首要修复)
你代码里存在一个致命的逻辑错误,这是导出速度极慢的最主要原因:
$num_fields = $result->rowCount();
PDO的rowCount()对于SELECT查询返回的是表的行数,不是字段数,你后续写了外层循环for ($i = 0; $i < $num_fields; $i++),相当于把整个表的所有行遍历了N次(N等于表的总行数),如果表有1万行,你就要循环1亿次,性能自然极差。
具体优化点
- 修复逻辑错误:把获取字段数的代码改为
$num_fields = $result->columnCount();,同时直接删除外层多余的for ($i = 0; $i < $num_fields; $i++)循环,只保留内层的while($row = $result->fetch())循环即可,单这一项优化就能让速度提升几十到上百倍。 - 避免全量内容驻留内存:不要把所有导出内容都拼到
$return字符串里,改用gzip流直接写入文件。用gzopen()打开压缩文件句柄,边读取数据库数据边用gzwrite()写入文件,内存占用可以从几十MB降到几MB,同时避免大字符串反复拼接、内存重新分配的开销。 - 调整压缩等级:原有代码用了最高压缩等级
9,压缩速度极慢,把压缩等级降到1~3,压缩速度提升非常明显,牺牲的少量压缩率几乎可以忽略。 - 生成批量INSERT语句:不要逐行生成
INSERT INTO xxx VALUES(...);,改为每1000行拼成一个批量插入语句,格式为INSERT INTO xxx VALUES (行1值), (行2值), ..., (行1000值);,可以大幅减少SQL文件体积,也减少字符串拼接的次数。 - 去掉冗余操作:删除没用的
preg_replace("/\\n/","\\n",$row[$j])代码,这段代码没有任何实际效果,只会无谓消耗性能;转义操作不要用addslashes,改用PDO自带的quote()方法,转义更准确、安全,性能也更高。 - 可选终极优化:如果你的环境允许调用系统命令,直接调用
mysqldump工具导出数据库,速度比PHP自研导出逻辑快5~10倍,还天然支持锁表、事务一致性等特性,不需要自己处理各种边界情况。
内容的提问来源于stack exchange,提问作者user14527894
相关产品推荐
相关产品推荐

