你向 MySQL 数据库插入 100w 条数据用了多久?

你向 MySQL 数据库插入 100w 条数据用了多久?
最新回答
丶小嘴灬乱亲

2022-06-17 04:50:14

向MySQL数据库插入100万条数据所需时间取决于多种因素,包括硬件配置、数据库优化策略以及插入方式。以下是关键影响因素及优化建议:

一、时间影响因素
  1. 硬件配置

    磁盘类型:SSD比HDD快约5-10倍(SSD约10-30分钟,HDD可能需数小时)。

    CPU与内存:多核CPU可加速多线程处理,内存不足会导致频繁磁盘交换。

  2. 插入方式

    单线程逐条插入:效率最低,100万条可能需数小时(如测试中10万条耗时10秒,换算后约16分钟)。

    多线程插入:通过并发减少连接耗时,但需注意表锁冲突(单表多线程可能因锁竞争导致性能下降)。

    批量插入:使用INSERT INTO ... VALUES (...), (...)或PreparedStatement.addBatch()可显著提速(10万条约10秒,100万条约1-2分钟)。

  3. 事务处理

    单条提交:每次提交都触发磁盘I/O,性能极差。

    批量提交(如每1000条提交一次):减少I/O次数,10万条约10秒,100万条约1-2分钟。

  4. 表结构优化

    索引与约束:主键、唯一索引会增加校验开销,插入前可临时禁用(需权衡数据一致性)。

    存储引擎:MyISAM比InnoDB快(无事务支持),但InnoDB更安全。

二、优化策略与代码示例
  1. 使用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(); // 提交剩余数据
  2. 多线程分表插入

    ExecutorService executor = Executors.newFixedThreadPool(4);for (int i = 0; i < 4; i++) { final int start = i * 250000; executor.submit(() -> { Connection conn = dataSource.getConnection(); // 类似批量插入逻辑,操作子范围数据 });}
  3. 调整事务与索引

    -- 临时禁用索引和约束(MySQL)ALTER TABLE large_table DISABLE KEYS;-- 插入完成后重建ALTER TABLE large_table ENABLE KEYS;
三、典型场景耗时
  • 未优化:单线程+逐条提交,SSD环境下约30-60分钟
  • 优化后:批量插入(1000条/批)+事务控制,SSD约1-5分钟
  • 极限优化:多线程分表+批量插入+临时禁用索引,SSD可压缩至30秒-2分钟
四、注意事项
  • 锁竞争:多线程插入同一表时,InnoDB的行锁可能导致线程阻塞。
  • 内存限制:批量过大可能引发OOM,需合理设置批次大小(如1000-5000条/批)。
  • 数据一致性:禁用索引或约束时需确保数据无冲突。
总结

通过批量操作事务控制硬件升级,插入100万条数据的时间可从数小时缩短至1-5分钟。实际耗时需结合具体环境测试,建议从单线程批量插入开始,逐步优化多线程和事务策略。