addall是真批量insert,一次sql;saveall是循环单条save,n条数据n次sql。前者快、无事件,适合纯新增;后者支持验证、自动填充等完整模型功能,但性能低、易超限。

addAll 是底层执行真批量 INSERT,saveAll 是循环调用单条 save,本质是语法糖。两者表面都支持“一次传多条”,但数据库交互方式、返回值、事务行为和适用场景完全不同。
底层执行逻辑不同
addAll 直接拼接成一条多值 INSERT 语句(如 INSERT INTO user (name,email) VALUES ('a','a@x'),('b','b@x')),只发起一次 SQL 请求;
saveAll 在 ThinkPHP 5.0 和 6.x 中均未改写为真批量,而是对每条数据调用一次 save(),即 N 条数据 = N 次 INSERT/UPDATE 查询。
- addAll 更快、更省连接资源,适合纯新增场景
- saveAll 会触发模型事件(如
beforeInsert)、自动时间戳、验证、类型转换等完整生命周期,但代价是性能下降明显 - 大批量时(如 >1000 条),saveAll 容易触发 MySQL
max_allowed_packet超限或连接超时,而 addAll 只需关注单条 SQL 长度是否合规
参数与数据结构要求不同
addAll 要求传入二维数组,键必须为数字索引(从 0 开始),且不能含主键字段(否则可能报错或被忽略);
saveAll 接收的二维数组中每条记录可含主键,若含主键且存在对应记录,会尝试更新(取决于模型配置和 isUpdate 状态)。
- addAll 示例:
$data = [['name'=>'A','email'=>'a@x'], ['name'=>'B','email'=>'b@x']] - saveAll 示例:
$data = [['id'=>1,'name'=>'A'], ['id'=>2,'name'=>'B']]—— 若 id 已存在,默认走更新逻辑 - saveAll 支持
saveAll($data, ['replace' => true]),但仍是逐条 REPLACE INTO,不是批量 REPLACE
返回值和错误处理差异
addAll 成功时返回插入记录数(整型),失败返回 false;
saveAll 返回一个模型对象数组,每个对象包含该条数据的完整实例(含自增 ID、自动填充字段等),便于后续链式操作或取值。
- 需要获取每条记录的 ID 或关联属性(如时间戳、加密字段结果)→ 选 saveAll
- 只关心是否成功、成功几条,且追求速度 → 选 addAll
- saveAll 出错时会中断,已执行的部分不会自动回滚(除非手动加事务包裹);addAll 出错即整批失败,原子性更强
事务与扩展能力对比
addAll 不依赖模型事件,不支持自动验证、自动完成、软删除等模型层特性;
saveAll 天然兼容模型全部功能,但加事务无法提升性能(只是保证 N 次操作的原子性)。
- 要做数据合法性校验、字段自动处理、关联写入 → 必须用 saveAll
- 导入日志、同步基础字典表等无业务逻辑的原始数据 → 优先 addAll
- 想兼顾性能与模型能力?可先用
validate(false)->allowField(true)简化 saveAll 行为,再分块(如每次 100 条)调用
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











