SQL server 批量插入数据速度分析

SQL server 批量插入数据速度分析

Java连接SQL server数据库,封装JDBC工具类如下:

public class JdbcUtils {
    private static String url = null;
    private static String user = null;
    private static String password = null;
    private static String driver = null;

    static{
        try {
            //创建properties对象
            Properties properties = new Properties();
            //加载配置文件
            properties.load(new FileInputStream("./src/db.properties"));
            //读取文件中相应数据
            driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            user = properties.getProperty("user");
            password = properties.getProperty("password");
            //加载驱动
            try {
                Class.forName(driver);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 封装connection
     * @return
     */
    public static Connection getConnection() {
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }
}

配置文件如下:

driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
url=jdbc:sqlserver://localhost:1433;DatabaseName=test
user=sa
password=123456

使用JDBC连接SQL server执行insert into方法大批量插入数据时,有如下三种方式:普通插入方式、最终提交方式、分批次插入方式

1.普通插入方式

使用insert into方式进行数据逐条插入,每插入一条数据,则立即执行executeUpdate()方法,

public class Demo1 {
    public static void main(String[] args) throws SQLException {
        // 起始时间
        long startTime = System.currentTimeMillis();
        //连接数据库
        Connection connection = JdbcUtils.getConnection();
        PreparedStatement cmd = connection.prepareStatement(
                "insert into CYMBUSWAY values(?,?,?,?,?,?,?,?,?)");
        for (int i = 1; i <= 2000000; i++) {// 200万条数据
            cmd.setInt(1, i);
            cmd.setInt(2, i);
            cmd.setFloat(3,4.333F);
            cmd.setFloat(4,5.666F);
            cmd.setFloat(5,2.33F);
            cmd.setFloat(6,7.33F);
            cmd.setString(7,"GY");
            cmd.setString(8,"DY");
            cmd.setString(9,"ZY");
            cmd.executeUpdate();
    }
        cmd.close();
        // 结束时间
        long endTime = System.currentTimeMillis();
        System.out.println("批量插入需要时间:" + (endTime - startTime)/1000 + "秒");
    }
}

插入200万数据,耗时为860s,约14mins

executeUpdate()注重及时性,每写一条sql语句就发送给数据库进行提交,保存起来,这样频繁操作数据库效率非常低。即使出现异常情况,不影响之前提交的数据。

2.最终提交方式

最终提交方式使用setAutoCommit(false);方法来取消数据库的自动提交功能,而在所有数据插入完毕后,再执行提交功能。

public class Demo2 {
    public static void main(String[] args) throws SQLException {
        // 起始时间
        long startTime = System.currentTimeMillis();
        //连接数据库
        Connection connection = JdbcUtils.getConnection();
        //取消自动提交
        connection.setAutoCommit(false);

        PreparedStatement cmd = connection.prepareStatement(
                "insert into CYMBUSWAY values(?,?,?,?,?,?,?,?,?)");
        for (int i = 1; i <= 2000000; i++) {// 200万条数据
            cmd.setInt(1, i);
            cmd.setInt(2, i);
            cmd.setFloat(3,4.333F);
            cmd.setFloat(4,5.666F);
            cmd.setFloat(5,2.33F);
            cmd.setFloat(6,7.33F);
            cmd.setString(7,"GY");
            cmd.setString(8,"DY");
            cmd.setString(9,"ZY");
            cmd.executeUpdate();
        }
        connection.commit();
        cmd.close();
        // 结束时间
        long endTime = System.currentTimeMillis();
        System.out.println("批量插入需要时间:" + (endTime - startTime)/1000 + "秒");
    }
}

插入200万数据,耗时为400s,约7mins

相比较于普通插入方式,最终提交方式减轻了数据库压力,但在数据写入过程中一旦出现代码异常,则所有数据全部提交失败。

3.分批次插入方式

结合最终提交方式,取消自动提交,采用将数据量进行分批次插入提交。200万数据分为10个批次,每10万条数据插入后进行一次commit提交

public class BatchInsert {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        // 起始时间
        long startTime = System.currentTimeMillis();
        //连接数据库
        Connection connection = JdbcUtils.getConnection();
        //取消自动提交
        connection.setAutoCommit(false);

        PreparedStatement cmd = connection.prepareStatement(
                "insert into CYMBUSWAY values(?,?,?,?,?,?,?,?,?)");
        for (int i = 1; i <= 2000000; i++) {// 200万条数据
            cmd.setInt(1, i);
            cmd.setInt(2, i);
            cmd.setFloat(3,4.333F);
            cmd.setFloat(4,5.666F);
            cmd.setFloat(5,2.33F);
            cmd.setFloat(6,7.33F);
            cmd.setString(7,"GY");
            cmd.setString(8,"DY");
            cmd.setString(9,"ZY");
            cmd.addBatch();
            if (i % 100000 == 0) {
                cmd.executeBatch();
                System.out.println(i);
            }
        }
        cmd.executeBatch();
        connection.commit();
        cmd.close();
        connection.close();
        // 结束时间
        long endTime = System.currentTimeMillis();
        System.out.println("批量插入需要时间:" + (endTime - startTime)/1000 + "秒");
    }
}

插入200万数据,耗时为54s,约1min

使用此种方法,每10万条数据commit一次去操作数据库,代码运行速度较快,数据库压力减轻。即使出现异常情况,仅影响本批次提交的数据。

你可能感兴趣的:(SQL server 批量插入数据速度分析)