839 字
约 2 分钟
7
S08-J04 · 批量操作与 SQL 注入器
适用读者:用
for循环插过一万条数据的人。
前置:S08-B04。
覆盖旧文:903(82) 1181(99) 375(366) + 空壳 1147 补写(E-S08-014)= 547 点。
上一篇:S08-J03 · 缓存:一级/二级与失效
下一篇:S08-A01 · 分库分表。
1. 一句话结论
批量插入的性能差异不在"SQL 好不好",在"网络往返次数":一万次 insert = 一万次往返;一条多值 insert = 一次。
| 方式 | SQL 次数 | 往返 |
|---|---|---|
循环 insert |
N 次 | N 次 |
MyBatis ExecutorType.BATCH |
N 次(攒批发送) | 分批 |
一条 insert ... values (...),(...) |
1 次 | 1 次 |
MP saveBatch |
底层用 BATCH executor | 分批 |
实测(S08-B01 的 Executor 对照):executor-type: batch 会把多条 DML 攒到 flushStatements 才发。
2. 三种批量写法
2.1 多值 INSERT(最快)
<insert id="batchInsert">
insert into sys_user(user_name, age) values
<foreach collection="list" item="u" separator=",">
(#{u.userName}, #{u.age})
</foreach>
</insert>
注意:单条 SQL 太长会撞 max_allowed_packet(MySQL),要分批(如 500 条/批)。
2.2 ExecutorType.BATCH
SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);
| 优点 | 缺点 |
|---|---|
| 内存友好(分批发) | 无法拿到每条的自增 ID(除非 JDBC 支持) |
| 适合海量插入 | 出错时定位困难 |
2.3 MP saveBatch
userMapper.insertBatchSomeColumn(list); // 需自定义
// 或 service.saveBatch(list, 500);
本质:循环 + BATCH executor。不是"一条 SQL"——要一条 SQL 得自己写 XML。
3. SQL 注入器(A-375,366 点)
MP 的"注入器"不是"SQL 注入漏洞",是"把方法注入到 Mapper"(名字容易吓人)。
public class MyInsertMethod extends AbstractMethod {
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo info) {
// 生成一条自定义 SQL 的 MappedStatement
}
}
| 用途 | 说明 |
|---|---|
| 加自定义通用方法 | 如 insertBatchSomeColumn(真正的多值插入) |
| 减少重复 XML | 一次定义,所有 Mapper 可用 |
判据:"这个 SQL 会在 5 个以上 Mapper 里重复吗?" 会 → 注入器;不会 → XML 更快。
4. 批量的四个注意点
| 点 | 说明 |
|---|---|
| 事务大小 | 太大 → 锁等待/回滚日志膨胀 |
| 分批大小 | 500–1000 条/批常见 |
| 唯一键冲突 | 整批失败 or 逐条跳过(INSERT IGNORE/ON DUPLICATE) |
| 自增 ID 回填 | BATCH 模式下可能拿不到 |
5. 五个误区
| 误区 | 真相 |
|---|---|
"saveBatch 是一条 SQL" |
是循环 + 批处理 |
| "批越大越快" | 受 packet/事务/锁限制 |
| "SQL 注入器是漏洞" | 是 MP 的扩展机制 |
| "BATCH 能拿到所有自增 ID" | 不一定 |
| "循环 insert 也行" | 网络往返是主要成本 |
6. 自检
- 三种批量方式的 SQL 次数差异?
- 多值 insert 的批量大小受什么限制?
ExecutorType.BATCH的代价是什么?- MP 的"SQL 注入器"到底是什么?
- 批处理为什么要注意事务大小?
7. 下一篇
S08-A01 · 分库分表:为什么、怎么分、带来什么
进阶层结束,架构师层开始:单表多大该分、分片键怎么选、分完之后的五个新问题。
本篇属于系列《S08 · MyBatis 持久层》。旧文来源:A-903/1181/375(空壳 1147 补写)。
S08-J04 · 批量操作与 SQL 注入器
https://www.clxhxhhr.top/posts/5290/ 评论
0 条
还没有评论,先写一条吧。