2022-06-17 04:50:14
向MySQL数据库插入100万条数据所需时间取决于多种因素,包括硬件配置、数据库优化策略以及插入方式。以下是关键影响因素及优化建议:
一、时间影响因素硬件配置
磁盘类型:SSD比HDD快约5-10倍(SSD约10-30分钟,HDD可能需数小时)。
CPU与内存:多核CPU可加速多线程处理,内存不足会导致频繁磁盘交换。
插入方式
单线程逐条插入:效率最低,100万条可能需数小时(如测试中10万条耗时10秒,换算后约16分钟)。
多线程插入:通过并发减少连接耗时,但需注意表锁冲突(单表多线程可能因锁竞争导致性能下降)。
批量插入:使用INSERT INTO ... VALUES (...), (...)或PreparedStatement.addBatch()可显著提速(10万条约10秒,100万条约1-2分钟)。
事务处理
单条提交:每次提交都触发磁盘I/O,性能极差。
批量提交(如每1000条提交一次):减少I/O次数,10万条约10秒,100万条约1-2分钟。
表结构优化
索引与约束:主键、唯一索引会增加校验开销,插入前可临时禁用(需权衡数据一致性)。
存储引擎:MyISAM比InnoDB快(无事务支持),但InnoDB更安全。
使用PreparedStatement批量插入
String sql = "INSERT INTO testdb.tuser (name, remark) VALUES (?, ?)";Connection conn = dataSource.getConnection();PreparedStatement pstmt = conn.prepareStatement(sql);for (int i = 0; i < 1000000; i++) { pstmt.setString(1, "Name" + i); pstmt.setString(2, "Remark" + i); pstmt.addBatch(); if (i % 1000 == 0) pstmt.executeBatch(); // 每1000条提交一次}pstmt.executeBatch(); // 提交剩余数据多线程分表插入
ExecutorService executor = Executors.newFixedThreadPool(4);for (int i = 0; i < 4; i++) { final int start = i * 250000; executor.submit(() -> { Connection conn = dataSource.getConnection(); // 类似批量插入逻辑,操作子范围数据 });}调整事务与索引
-- 临时禁用索引和约束(MySQL)ALTER TABLE large_table DISABLE KEYS;-- 插入完成后重建ALTER TABLE large_table ENABLE KEYS;通过批量操作、事务控制和硬件升级,插入100万条数据的时间可从数小时缩短至1-5分钟。实际耗时需结合具体环境测试,建议从单线程批量插入开始,逐步优化多线程和事务策略。