MySQL + JDBC 实现批量插入(千万数据)

导读:本篇文章讲解 MySQL + JDBC 实现批量插入(千万数据),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

1. 配置my.ini文件

bulk_insert_buffer_size=120M 或者更大

将insert语句的长度设为最大。

Max_allowed_packet=1M

Net_buffer_length=8k

可以通过navicat直接查询修改:

 SHOW VARIABLES where Variable_name = 'bulk_insert_buffer_size'
 
 set bulk_insert_buffer_size = 104857600

2. 查看设置的参选有没有生效

SHOW VARIABLES;

image-20211208114024338

bulk_insert_buffer_size默认是8M,我们要把它调成100M或百兆以上,也不要太大。下面看调整好的,如下图:

image-20211208115520905

3. 数据插入

表结构:

image-20211208131212101
建议多线程+批量插入执行,否则耗时太长,单线程插入100W跳数据插入了半小时…

开启十个线程,每个线程插入100W数据:

可以看出这个实际还是可以接受的!

image-20211208130516401

代码如下:

public class BatchMain {

    public static void main(String[] args) throws Exception {
        //嘎嘎快
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            executorService.execute(new BatchThread());
        }

        //batchInsert();
    }

    static class BatchThread implements Runnable {

        @SneakyThrows
        @Override
        public void run() {
            long start = System.currentTimeMillis();

            Connection conn;
            String driver = "com.mysql.jdbc.Driver";
            String url = "jdbc:mysql://localhost:3306/demo?useTimezone=true&serverTimezone=GMT%2B8&characterEncoding=utf-8";
            String user = "root";
            String password = "123456";
            Class.forName(driver);
            conn = DriverManager.getConnection(url, user, password);

            conn.setAutoCommit(false);
            PreparedStatement ps = null;
            String sql = "insert into test(name,addr,age) values (?,?,?)";
            ps = conn.prepareStatement(sql); // 批量插入时ps对象必须放到for循环外面
            for (int i = 0; i < 1000000; i++) {
                ps.setString(1, "mary_" + i);
                ps.setString(2, "西城区" + i + "号路");
                ps.setInt(3, (i + 1));

                ps.addBatch();
                // 每1000条记录插入一次
                if (i % 10000 == 0) {
                    ps.executeBatch();
                    conn.commit();
                    ps.clearBatch();
                }
            }
            // 剩余数量不足10000
            ps.executeBatch();
            conn.commit();
            ps.clearBatch();
            long end = System.currentTimeMillis();
            System.out.println(end - start);
        }
    }

    //批量插入
    public static void batchInsert() throws Exception {
        long start = System.currentTimeMillis();

        Connection conn;
        String driver = "com.mysql.jdbc.Driver";
        String url = "jdbc:mysql://localhost:3306/demo?useTimezone=true&serverTimezone=GMT%2B8&characterEncoding=utf-8";
        String user = "root";
        String password = "123456";
        Class.forName(driver);
        conn = DriverManager.getConnection(url, user, password);

        conn.setAutoCommit(false);
        PreparedStatement ps = null;
        String sql = "insert into test(name,addr,age) values (?,?,?)";
        ps = conn.prepareStatement(sql); // 批量插入时ps对象必须放到for循环外面
        for (int i = 0; i < 1000; i++) {
            ps.setString(1, "mary_" + i);
            ps.setString(2, "西城区" + i + "号路");
            ps.setInt(3, (i + 1));

            ps.addBatch();
            // 每1000条记录插入一次
            if (i % 1000 == 0) {
                ps.executeBatch();
                conn.commit();
                ps.clearBatch();
            }
        }
        // 剩余数量不足10000
        ps.executeBatch();
        conn.commit();
        ps.clearBatch();
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }

    //巨慢无比 100w数据需要30分钟
    public static void nomarl() throws Exception {
        Connection conn;
        PreparedStatement stmt;
        String driver = "com.mysql.jdbc.Driver";
        String url = "jdbc:mysql://localhost:3306/demo?useTimezone=true&serverTimezone=GMT%2B8&characterEncoding=utf-8";
        String user = "root";
        String password = "123456";
        //String sql = "insert into test values (?,?,?)";
        String sql = "insert into test(name,addr,age) values (?,?,?)";
        Class.forName(driver);
        conn = DriverManager.getConnection(url, user, password);
        stmt = (PreparedStatement) conn.prepareStatement(sql);
        System.out.println(new Date());
        /* —————————————————————————— */
        for (int i = 1; i < 10000000; i++) {
            stmt.setString(1, "mary_" + i);
            stmt.setString(2, "西城区" + i + "号路");
            stmt.setInt(3, (i + 1));
            stmt.executeUpdate();
        }
        System.out.println(new Date());

        try {
            if (stmt != null) {
                stmt.close();
            }
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/16780.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!