提速核心是绕过orm单条事务开销,改用原生批量插入+手动事务控制:关闭自动提交、拼接insert语句、分批1000–5000行、临时禁用外键与唯一性检查、每千条clear缓存并流式读取。

用 Doctrine ORM 直接 save() 逐条写入,几万条数据可能卡十几分钟。提速核心不是换框架,而是绕过 ORM 的单条事务开销,改用原生批量机制 + 事务控制。
关闭自动提交,手动包裹事务
Doctrine 默认每 flush() 都触发一次 commit。必须显式禁用 autocommit,并用原生连接执行事务:
- 获取底层 PDO 连接:
$conn = $em->getConnection(); - 执行
$conn->executeStatement('START TRANSACTION'); - 插入完成后调用
$conn->executeStatement('COMMIT'); - 出错时用
ROLLBACK回滚,避免残留脏数据
用原生 INSERT ... VALUES 批量拼接
别依赖 $em->persist() + flush()。把数据组装成标准 SQL:
- 每批控制在 1000–5000 行(避开 MySQL
max_allowed_packet限制) - 拼接格式:
INSERT INTO table (col1,col2) VALUES (v1,v2), (v3,v4), ... - 注意参数转义——用
$conn->quote()处理字符串,避免 SQL 注入 - 数值、布尔值等直接拼接,不加引号
临时禁用索引与约束(仅限导入阶段)
如果确认数据干净,可大幅提升写入速度:
- 导入前执行:
SET FOREIGN_KEY_CHECKS = 0;和SET UNIQUE_CHECKS = 0; - 导入完成后再恢复:
SET FOREIGN_KEY_CHECKS = 1;和SET UNIQUE_CHECKS = 1; - 注意:此操作需有 DDL 权限,且仅适用于一次性全量导入场景
分批次处理 + 内存释放
避免 Doctrine 管理大量 Entity 导致内存溢出:
- 每处理 1000 条就调用
$em->clear();清空一级缓存 - 不要把全部数据先 load 到对象数组再循环 —— 改为流式读取(如用
fgetcsv或分页查源数据) - PHP CLI 模式下建议设
ini_set('memory_limit', '1G');防止中断











