-- 低效写法:逐条插入
INSERT INTO table (col1, col2) VALUES (1, 'a');
INSERT INTO table (col1, col2) VALUES (2, 'b');
-- 高效写法:批量插入
INSERT INTO table (col1, col2) VALUES
(1, 'a'), (2, 'b'), (3, 'c'), ...;
500~2000
行(避免超出 max_allowed_packet
)。START TRANSACTION;
INSERT INTO table ...;
INSERT INTO table ...;
...
COMMIT;
undo log
膨胀,需根据内存调整事务批次(如每 1万~10万
行提交一次)。LOAD DATA INFILE
**INSERT
快 20倍以上,跳过了SQL解析和事务开销。LOAD DATA LOCAL INFILE '/path/data.csv'
INTO TABLE table
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n';
-- 禁用索引
ALTER TABLE table DISABLE KEYS;
-- 插入数据...
-- 重建索引
ALTER TABLE table ENABLE KEYS;
SET FOREIGN_KEY_CHECKS = 0;
-- 插入数据...
SET FOREIGN_KEY_CHECKS = 1;
innodb_flush_log_at_trx_commit
**:
1
(每次事务提交都刷盘),改为 0
或 2
可减少磁盘I/O。0
:每秒刷盘(可能丢失1秒数据)。2
:提交时写入OS缓存,不强制刷盘。innodb_buffer_pool_size
**:
70%~80%
),提高数据缓存命中率。innodb_autoinc_lock_mode
**:
2
(交叉模式),减少自增锁竞争(需MySQL 8.0+)。max_allowed_packet
**:
4MB
),避免批量插入被截断。bulk_insert_buffer_size
**:
8MB
)。back_log
**:增大连接队列长度,应对高并发插入。innodb_doublewrite
**:关闭双写机制(牺牲数据安全换取性能)。innodb_file_per_table
避免表空间碎片。PARTITION BY
)。// Java示例
String sql = "INSERT INTO table (col1, col2) VALUES (?, ?)";
PreparedStatement ps = conn.prepareStatement(sql);
for (Data data : list) {
ps.setInt(1, data.getCol1());
ps.setString(2, data.getCol2());
ps.addBatch();
}
ps.executeBatch();
优化方法 | 插入10万条耗时(秒) |
---|---|
逐条插入(默认) | 120 |
批量插入(1000行/次) | 5 |
LOAD DATA INFILE |
1.5 |
LOAD DATA INFILE
或批量插入。通过上述方法,可在MySQL中实现每秒数万甚至数十万条的高效插入。
如果觉得博客文章对您有帮助,异或土豪有钱任性,可以通过以下扫码向我捐助。也可以动动手指,帮我分享和传播。您的肯定,是我不懈努力的动力!感谢各位亲~