INSERT 是寫入頻率最高的 SQL,性能直接決定業務吞吐上限。本文匯總官方文檔最佳實踐、引擎層原理、實測數據對比,提煉 8 大核心優化策略與 Java 落地代碼。
插入一行耗時分解(比例概估):
| 階段 | 佔比 | 說明 | |||
|---|---|---|---|---|---|
| Connecting | 3% | 建立連接 | |||
| Sending query | 2% | 網絡傳輸 | |||
| Parsing query | 2% | SQL 解析 | |||
| Inserting row | 1×行大小 | 數據寫入 | |||
| Inserting indexes | 1×索引數 | 二級索引維護,O(log N) | |||
| Closing | 1% | 清理上下文 |
| 方案 | 1千行 | 5千行 | 1萬行 | 5萬行 | 10萬行 |
|---|---|---|---|---|---|
| 單條 INSERT | 24s | 160s | 277s | -- | -- |
| 多值 INSERT (1000/批) | 2s | 6s | 11s | 51s | 99s |
| 10線程並發多值 (1000/批) | 5-10s | 27-49s | 49-84s | 275-377s | 552-648s |
| 10線程並發 (表已有100萬,再插900萬) | 499s/10萬 | ~ | ~ | ~ | 4200s/900萬 |
OPTIMIZE TABLE 或分區/分表
public void batchInsert(List records) {
String sql = "INSERT INTO t (a,b,c) VALUES (?,?,?)";
try (Connection conn = ds.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)) {
conn.setAutoCommit(false);
int batchSize = 1000;
int count = 0;
for (Record r : records) {
ps.setObject(1, r.getA());
ps.setObject(2, r.getB());
ps.setObject(3, r.getC());
ps.addBatch();
if (++count % batchSize == 0) {
ps.executeBatch();
conn.commit();
ps.clearBatch();
}
}
ps.executeBatch();
conn.commit();
}
}
INSERT 優化的本質是將離散的隨機寫入轉化為連續的順序批次。掌握 8 大策略,根據引擎、業務、數據量靈活組合,才能榨乾磁盤 IOPS 的每一分價值。