向MySQL插入100w条数据,该怎么做?

使用MySQL存储过程插入

那么从sql层面上我们该怎么插入100万条数据呢,无脑直接写个循环?那就使用存储过程试试看吧

DROP PROCEDURE IF EXISTS proc_insert()
	DELIMITER $
	CREATE PROCEDURE pro_insert2()
 	BEGIN
    DECLARE i INT DEFAULT 1;
    WHILE i<=1000000 DO
    INSERT INTO student VALUES(i,马老师,1970-02-02,广东深圳,60,60,60);
    SET i = i+1;
    END WHILE;
    END $

调用该存储过程后执行时间如下

JDBC往数据库中普通插入方式

同样先来个粗暴的100万次for循环,代码如下

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * @author admin
 * @version 1.0.0
 * @ClassName InsertForDemo.java
 * @createTime 2020年12月06日 15:17:58
 */
public class InsertForDemo {
          
   
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
          
   

        long start = System.currentTimeMillis();
        Connection con = SqlTools.getConnection();
        System.out.println(con);
        String sql = "insert into emp (uid,name,age,hiredate,salary,deptno) values(?,?,?,?,?,?)";
        PreparedStatement ps = con.prepareStatement(sql);
        for (int i = 0; i < 1000000; i++) {
          
   

            ps.setString(1, SqlTools.getTrimUUID());
            ps.setString(2, SqlTools.getChineseName());
            ps.setInt(3, SqlTools.getNum(18, 60));
            ps.setString(4, SqlTools.getCurrTime());
            ps.setInt(5, SqlTools.getNum(5000, 500000));
            ps.setInt(6, SqlTools.getNum(1, 50));

            ps.execute();

        }
        con.close();
        long end = System.currentTimeMillis();
        System.out.println("插入100w条数据,for循环耗时:" + (end - start) + "ms");

    }
}

执行用时653550ms 在讨论批量处理之前,先说说遇到的坑。MySQL驱动jar包,使用过低版本(5.1.13以下)会导致停止掉java程序后,mysql还在不断的往数据库中插入数据,最后不得不停止掉数据库服务才停下来…

使用事务批处理提交方式

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class InsertDataByTxDemo {
          
   
    //  insert into emp values (uid,name,age,hiredate,salary,deptno)
    public static void main(String[] args) throws SQLException, ClassNotFoundException {
          
   
        Connection con = SqlTools.getConnection();
        String sql = "insert into emp values(?,?,?,?,?,?)";
        try {
          
   
            con.setAutoCommit(false);
            PreparedStatement pst = con.prepareStatement(sql);
            long start = System.currentTimeMillis();
            for (int i = 0; i < 10; i++) {
          
   
                long start2 = System.currentTimeMillis();
                // 每一轮插入10万条
                for (int j = 0; j < 100000; j++) {
          
   
                    pst.setString(1, SqlTools.getTrimUUID());
                    pst.setString(2, SqlTools.getChineseName());
                    pst.setInt(3, SqlTools.getNum(18, 60));
                    pst.setString(4, SqlTools.getCurrTime());
                    pst.setInt(5, SqlTools.getNum(5000, 50000));
                    pst.setInt(6, SqlTools.getNum(1, 50));
                    pst.addBatch();
                }
                pst.executeBatch();
                pst.clearBatch();
                con.commit();
                long end2 = System.currentTimeMillis();
                System.out.println("第" + (i + 1) + "轮执行时间:" + (end2 - start2) + "ms");
            }

            long end = System.currentTimeMillis();
            System.out.println("总耗时:" + (end - start) + "ms");//168662ms

        } catch (SQLException e) {
          
   
            e.printStackTrace();
        } finally {
          
   
            con.close();
        }
    }
}

显然批处理事务提交的效果还不错。

经验分享 程序员 微信小程序 职场和发展