千万级数据插入需组合优化:1. 多值insert(500~2000行/批)减少解析与io;2. 关autocommit、手动事务(每万~五万行提交);3. 插入前删非主键索引、禁外键检查;4. 主键顺序插入;5. 优先用load data infile(快5–20倍)。

千万级数据插入不是“能不能插”的问题,而是“怎么插不翻车”的问题。单条 INSERT 在百万级以上基本不可用——它会把网络、日志、锁、索引维护全拖垮。真正能扛住千万量级的,是组合策略:SQL 语法压缩 + 事务控制 + 配置调优,缺一不可。
用多值 INSERT 合并行,但别贪多
MySQL 原生支持一条 INSERT 插入多行,这是最基础也最关键的提速点。它直接砍掉 N 次 SQL 解析、N 次网络往返、N 次 binlog/redo 写入开销。
- 每批控制在
500~2000行之间:字段越宽(比如含大文本、JSON),越要往小取;默认max_allowed_packet=4M,插 1000 行 varchar(500) 就可能超限 - 别手拼大 SQL 字符串:Java 里用 MyBatis-Plus 的
saveBatch(list, batchSize),底层自动切分;JDBC 用addBatch()+executeBatch(),避免 OOM - 错误现象:
Packets larger than max_allowed_packet are not allowed—— 这不是代码错,是 MySQL 拒收,必须调max_allowed_packet
关掉 autocommit,手动管事务
InnoDB 默认每条语句都自动提交,等于每插一行就刷一次 redo log 到磁盘。千万级下,光日志刷盘就能卡死 I/O。
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
- 显式执行
START TRANSACTION,所有批量INSERT包在里面,最后COMMIT - 每
10000~50000行提交一次:太小起不到合并效果;太大易触发undo log膨胀或锁等待超时 - 注意连接状态:MyBatis-Plus 的
saveBatch默认不开启事务,得包在@Transactional方法里,否则还是单条提交
避开索引和约束的实时维护成本
插入时每行都要更新 B+ 树索引、校验唯一约束、检查外键,这些操作在千万级下是指数级开销。
- 导入前临时禁用:
ALTER TABLE t DISABLE KEYS(仅对 MyISAM 有效);InnoDB 下更有效的是删非主键索引,导入完重建 - 关外键检查:
SET FOREIGN_KEY_CHECKS = 0,导入完再设回1 - 主键尽量顺序插入:如果主键是自增
id,确保数据按id升序生成;乱序插入会导致 B+ 树频繁分裂,写放大严重
真到千万级,绕过 SQL 直接上 LOAD DATA INFILE
当数据已落盘为 CSV 或文本,LOAD DATA INFILE 是目前 MySQL 最快的写入方式,比最优 SQL 批量快 5–20 倍——它跳过了 SQL 解析、权限校验、客户端传输等全部中间环节。
- 必须满足:
local_infile=ON(服务端和客户端都要开),文件路径对 MySQL 进程可读(不是你本地路径) - 示例命令:
LOAD DATA LOCAL INFILE '/tmp/data.csv' INTO TABLE t FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n' - 坑点:CSV 中有换行、引号、逗号时需严格转义;字符集不一致会乱码,务必加
CHARACTER SET utf8mb4
真正难的不是选哪个方案,而是判断数据来源、下游依赖、运维权限这三者的交集——比如生产库不允许开 local_infile,那就只能靠 SQL + 事务 + 配置组合;又比如表上有强业务唯一约束不能删,那索引优化就得让步。所有策略都得贴着真实约束落地,而不是堆参数。










