慢查詢優化解決讀問題,批量寫入優化解決寫問題。本文系統總結 MyISAM/InnoDB 分層優化策略,實測對比「多值 INSERT、事務包裹、有序插入」三大核心手段,揭示千萬級數據下效能差異達 100 倍的關鍵路徑。
ALTER TABLE tbl_name DISABLE KEYS;
-- 批量導入數據
LOAD DATA INFILE ... / INSERT ...
ALTER TABLE tbl_name ENABLE KEYS;
原理:導入階段暫停非唯一索引維護,完成後一次性重建。僅適用非空表,空表默認延遲建索引。
SET UNIQUE_CHECKS=0 → 導入 → SET UNIQUE_CHECKS=1SET AUTOCOMMIT=0 → 批量提交 → SET AUTOCOMMIT=1測試表:insert_table(datetime PK, uid, content, type)
-- 原始:N 條單獨 INSERT
INSERT INTO insert_table VALUES ('0', 'userid_0', 'content_0', 0);
INSERT INTO insert_table VALUES ('1', 'userid_1', 'content_1', 1);
...
-- 優化:單條 SQL 多 VALUES
INSERT INTO insert_table VALUES
('0', 'userid_0', 'content_0', 0),
('1', 'userid_1', 'content_1', 1),
...;
收益來源:減少 SQL 解析、網絡 RTT、Binlog/Redo Log 刷盤頻率
START TRANSACTION;
INSERT ...; INSERT ...; ...;
COMMIT;
收益來源:減少事務提交同步開銷(fsync)
-- 無序:隨機 datetime 導致 B+ 樹頻繁分裂
INSERT ... VALUES ('2', ...);
INSERT ... VALUES ('0', ...);
INSERT ... VALUES ('1', ...);
-- 有序:按 datetime 遞增
INSERT ... VALUES ('0', ...);
INSERT ... VALUES ('1', ...);
INSERT ... VALUES ('2', ...);
收益來源:順寫追加模式,索引維護開銷最小
| 數據量 | 單條 INSERT | 多值 INSERT | 多值+事務 | 多值+事務+有序 |
|---|---|---|---|---|
| 100 | 0.8 | 0.1 | 0.05 | 0.04 |
| 1,000 | 6.2 | 0.6 | 0.3 | 0.25 |
| 10,000 | 58 | 4.1 | 1.8 | 1.2 |
| 100,000 | 620 | 38 | 15 | 8 |
| 1,000,000 | 6500 | 420 | 180 | 65 |
| 10,000,000 | OOM | 崩潰 | 崩潰 | 580 |
innodb_buffer_pool_size 時性能崩塌(脏頁刷盤風暴)
Connection conn = DriverManager.getConnection(url, user, pass);
conn.setAutoCommit(false); // 關閉自動提交
String sql = "INSERT INTO insert_table (datetime, uid, content, type) VALUES (?, ?, ?, ?)";
PreparedStatement ps = conn.prepareStatement(sql);
for (Record r : records) {
ps.setString(1, r.datetime);
ps.setString(2, r.uid);
ps.setString(3, r.content);
ps.setInt(4, r.type);
ps.addBatch();
// 批次提交控制(防止批次過大超過 max_allowed_packet / innodb_log_buffer_size)
if (++count % 1000 == 0) {
ps.executeBatch();
conn.commit();
ps.clearBatch();
}
}
ps.executeBatch(); // 餘數提交
conn.commit();
conn.setAutoCommit(true);
| 參數 | 建議值 | 作用 |
|---|---|---|
| max_allowed_packet | 64M-256M | 單條 SQL 最大長度,限制多值 INSERT 批次大小 |
| innodb_log_buffer_size | 64M-256M | 事務日志緩衝,批次提交前不刷盤 |
| innodb_flush_log_at_trx_commit | 2 (批量導入期) | 提交時僅寫 OS Cache,由後台刷盤,極大提升寫入吞吐 |
| innodb_buffer_pool_size | 物理內存 60-70% | 容納熱數據與脏頁,避免大批次導入時頻繁刷盤 |
max_allowed_packet 限制,動態計算單行大小反推批次innodb_log_buffer_size 觸發同步刷盤,分批提交(建議 1000-5000 行/批)INSERT IGNORE/ON DUPLICATE KEY UPDATESET FOREIGN_KEY_CHECKS=0,導入後恢復SET SQL_LOG_BIN=0 跳過 Binlog 寫入批量插入優化不是單一技巧,而是「有序數據 + 多值合並 + 事務批次 + 參數調優」的系統工程。千萬級穩定寫入,有序是前提,分批是保障,參數是放大器。