-- 低效写法:逐条插入
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中实现每秒数万甚至数十万条的高效插入。
如果觉得博客文章对您有帮助,异或土豪有钱任性,可以通过以下扫码向我捐助。也可以动动手指,帮我分享和传播。您的肯定,是我不懈努力的动力!感谢各位亲~