MySQL 單條插入開銷含連接、解析、寫入、索引維護、提交五個階段。本文拆解插入耗時組成,給出六大優化技巧與實測效果對比。
表大小以 N log N (B+Tree) 減慢索引插入。
| 技巧 | 適用場景 | 核心命令/代碼 | 預期提升 |
|---|---|---|---|
| 多值 INSERT | 同一客戶端批量寫入 | INSERT INTO t (a,b) VALUES (1,2),(3,4),(5,6); | 比單條循環快 5-10 倍(減少解析、網絡往返) |
| INSERT DELAYED | 多客戶端寫入、可容忍延遲 | INSERT DELAYED INTO t ... | 客戶端即時返回,服務器批量刷盤(MyISAM/MEMORY 支持,InnoDB 5.6+ 忽略 DELAYED) |
| LOAD DATA INFILE | 文本文件導入、大量數據初始化 | LOAD DATA INFILE 'data.txt' INTO TABLE t; | 比 INSERT 快 **20 倍** |
| 禁用索引 + 導入 + 重建 | 大表全量裝載、MyISAM/InnoDB | 1. myisamchk --keys-used=0 -rq tbl 禁用索引2. LOAD DATA INFILE3. myisamchk -r -q tbl 重建索引(內存排序、避免隨機 IO) | 索引維護從 O(N log N) 降為 O(N) 掃描排序 |
| 鎖表批量提交 | 單客戶端大批量、可獨佔表 | LOCK TABLES t WRITE; INSERT ...; INSERT ...; UNLOCK TABLES; | 索引緩衝區僅刷盤一次,整體提速 ~40% |
| MyISAM 並發插入 | 無刪除空洞的 MyISAM 表 | 無需額外操作,concurrent_insert=1 (默認) | SELECT 與 INSERT 並行無阻塞 |
CREATE TABLE t ...(僅結構,無索引)FLUSH TABLESmyisamchk --keys-used=0 -rq /path/to/t 禁用索引LOAD DATA INFILE 'data.txt' INTO TABLE t 极速寫入myisampack /path/to/t (可選,壓縮只讀表)myisamchk -r -q /path/to/t 重建索引(內存構建 B-Tree,避免磁盤尋道)FLUSH TABLES此流程將被未來版本整合進 LOAD DATA INFILE 內部。
innodb_flush_log_at_trx_commit = 2(導入期間臨時調整,風險秒級丟失 1 秒數據)innodb_autoinc_lock_mode = 2(interleaved 模式,配合多值 INSERT 最大化自增並發)SET FOREIGN_KEY_CHECKS=0; 導入後 =1SET UNIQUE_CHECKS=0; 導入後 =1LOAD DATA INFILE(InnoDB 同樣受益於批量、減少解析)batchSize=1000-5000),框架層面自動批量(Hibernate hibernate.jdbc.batch_size、MyBatis BATCH 模式)。插入優化核心:**減少解析往返、批量緩衝刷盤、延遲索引維護**。根據數據量、業務容忍度、存儲引擎選擇組合拳。