高效的批量插入数据

如果直接使用循环进行批量插入数据,那么只能每次循环时就填充占位符,然后进行插入操作,这让插入1000000万的数据十分低效。

下面代码只演示了这样插入20000行数据就需要30多秒了。

package com.batchinsert;

import com.utils.JDBCUtils;

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

/**
 * @author 承夕
 * @date 2020/3/1 0001 - 20:40
 * @contact:https://github.com/chengxi0
 */
public class InsertBatchDeom1 {
    public static void main(String[] args) {
        String sql = "insert into goods (name) values (?) ;" ;


        Connection conn = null ;
        PreparedStatement pstm = null;


        try {
            //获取连接
            conn = JDBCUtils.getConnection();

            //获取PreparedStatement
            pstm = conn.prepareStatement(sql);

            long start = System.currentTimeMillis();

            for (int i = 1; i <= 20000; i++) {
                //填充占位符
                pstm.setObject(1, "name_" + i);
                pstm.executeUpdate() ;
            }

            long end = System.currentTimeMillis();
            System.out.println(end-start);
            //33611  这是用时的毫秒值
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            JDBCUtils.closeResource(conn, pstm, null);
        }

    }
}

第一次优化:

类比于IO操作里面的read()方法和read(byte[])方法,前者类似于前面的每次填充占位符然后插入操作,那么,能否一次攒够这么多插入操作,再在数据库中进行一次性插入呢??因此需要使用到三个方法:addBatch()  executeBatch()  clearBatch()

前提

默认情况下,Mysql中是关闭批处理的,因此需要在配置文件中添加上属性:rewriteBatchedStatements=true

url=jdbc:mysql://localhost:3306/test?&rewriteBatchedStatements=true

使用更新的MySQL驱动 :mysql-connector-java-5.1.37-bin.jar

package com.batchinsert;

import com.utils.JDBCUtils;

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

/**
 * @author 承夕
 * @date 2020/3/1 0001 - 20:40
 * @contact:https://github.com/chengxi0
 */
public class InsertBatchDeom2 {
    public static void main(String[] args) {
        String sql = "insert into goods (name) values (?) " ;


        Connection conn = null ;
        PreparedStatement pstm = null;


        try {
            //获取连接
            conn = JDBCUtils.getConnection();

            //获取PreparedStatement
            pstm = conn.prepareStatement(sql);

            long start = System.currentTimeMillis();

            for (int i = 1; i <= 1000000; i++) {
                //填充占位符
                pstm.setObject(1, "name_" + i);

                //攒‘sql’
                pstm.addBatch();
                if (i % 500 == 0) {
                    //批量执行
                    pstm.executeBatch();
                    //清理攒到的sql
                    pstm.clearBatch();
                }
            }

            long end = System.currentTimeMillis();
            System.out.println(end-start);
            //9249  这是1000000数据用时的毫秒值
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            JDBCUtils.closeResource(conn, pstm, null);
        }
    }
}

此时已经可以在处理1000000数据只是10秒钟不到的时间,那么是否还可以继续优化呢??

第二次优化:

默认情况下,在每次执行操作之后会进行连接提交的,在这里需要不少时间。可以设置在执行完1000000的数据插入操作再进行提交。

conn.setAutoCommit(false);
package com.batchinsert;

import com.utils.JDBCUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * @author 承夕
 * @date 2020/3/1 0001 - 20:40
 * @contact:https://github.com/chengxi0
 */
public class InsertBatchDeom3 {
    public static void main(String[] args) {
        String sql = "insert into goods (name) values (?) " ;


        Connection conn = null ;
        PreparedStatement pstm = null;


        try {
            //获取连接
            conn = JDBCUtils.getConnection();

            //我们在获取连接的时候设置不自动进行提交
            conn.setAutoCommit(false);

            //获取PreparedStatement
            pstm = conn.prepareStatement(sql);

            long start = System.currentTimeMillis();

            for (int i = 1; i <= 1000000; i++) {
                //填充占位符
                pstm.setObject(1, "name_" + i);

                //攒‘sql’
                pstm.addBatch();
                if (i % 500 == 0) {
                    //批量执行
                    pstm.executeBatch();
                    //清理攒到的sql
                    pstm.clearBatch();
                }
            }

            long end = System.currentTimeMillis();
            System.out.println(end-start);
            //5413  这是1000000数据用时的毫秒值

            //插入完再提交咯
            conn.commit();

        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            JDBCUtils.closeResource(conn, pstm, null);
        }
    }
}

这里需要的时间仅仅5秒多一点。

发布了55 篇原创文章 · 获赞 4 · 访问量 1056

猜你喜欢

转载自blog.csdn.net/weixin_45062761/article/details/104601228
今日推荐