JDBC的批处理

JDBC使用MySQL处理大数据的时候,自然而然的想到要使用批处理,

普通的执行过程是:每处理一条数据,就访问一次数据库;

而批处理是:累积到一定数量,再一次性提交到数据库,减少了与数据库的交互次数,所以效率会大大提高。

注意在mysql中:数据库连接中的参数rewriteBatchedStatements相当重要,如果不开启rewriteBatchedStatements=true,那么jdbc会把批量插入当做一行行的单条处理,也即没有达到批量插入的效果。该值在mysql中的默认值是false,mysql8.0版本。其中还有一个属性allowMultiQueries,该属性是在查询的时候,允许在一个查询语句中,使用';'号来分隔多个查询,但是要注意,它不影响addBatch()和executeBatch()方法,这两个方法依赖于rewritebatchstatement属性。

mysql连接参数的文档:https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-configuration-properties.html

1.JDBC实现批处理,预编译和非预编译

1、使用Statement对象添加要批量执行SQL语句,如下:

Statement.addBatch(sql1);
Statement.addBatch(sql2);
Statement.addBatch(sql3);
Statement.executeBatch();
Statement.clearBatch();

优点:可以向数据库发送多条不同的SQL语句。
缺点:SQL语句没有预编译,当向数据库发送多条语句相同,但仅参数不同的SQL语句时,需重复写上很多条SQL语句。

2.使用PrepareStatement

    @Test
    public void testJdbcBatchHandleByPrepareStatement(){
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        
        Instant start = Instant.now();
        try{
            conn = JdbcUtil.getConnection();
            String sql = "insert into testbatch(id,name) values(?,?)";
            st = conn.prepareStatement(sql);
            for(int i=1;i<10000;i++){
                st.setInt(1, i);
                st.setString(2, UUID.randomUUID().toString());
                st.addBatch();
                // 这种主要是为了避免内存不足
                // if(i%1000==0){
                //    st.executeBatch();
                //    st.clearBatch();
                // }
            }
            st.executeBatch();
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtil.release(conn, st, rs);
        }
        Instant end = Instant.now();
        System.out.println("花费时间:"+ Duration.between(start, end).toMillis());
    }

优点:发送的是预编译后的SQL语句,执行效率高。
缺点:只能应用在SQL语句相同,但参数不同的批处理中。因此此种形式的批处理经常用于在同一个表中批量插入数据,或批量更新表的数据。

2.PreparedStatement不使用批处理

PreparedStatement preparedStatement = conn.prepareStatement("insert into t(name,price,score) values(?,?,?)");

for(int i=0; i<10000; i++){
    preparedStatement.setString(1, randomStr());
    preparedStatement.setDouble(2, randomPrice());
    preparedStatement.setInt(3, randomScore());
    pstmt.execute();
}

最终用时28秒

3.prepareStatement使用批处理

PreparedStatement preparedStatement = connection.prepareStatement(sql);
for(int i=0;i<10000;i++){
    preparedStatement.setString(1, randomStr());
    preparedStatement.setDouble(2, randomPrice());
    preparedStatement.setInt(3, randomScore());
    preparedStatement.addBatch();
}
preparedStatement.executeBatch();
preparedStatement.clearBatch();

最终用时0.3秒,效率差距啊。

4.prepareStatement开启事务,不开启批处理

connection.setAutoCommit(false);
PreparedStatement preparedStatement = connection.prepareStatement(sql);
for(int i=0;i<10000;i++){
    preparedStatement.setString(1, randomStr());
    preparedStatement.setDouble(2, randomPrice());
    preparedStatement.setInt(3, randomScore());
    preparedStatement.execute();
}
connection.commit();

最终用时3秒,还不错。

5.prepareStatement开启事务,开启批处理

connection.setAutoCommit(false);
PreparedStatement preparedStatement = connection.prepareStatement(sql);
for(int i=0;i<10000;i++){
      preparedStatement.setString(1, randomStr());
      preparedStatement.setDouble(2, randomPrice());
      preparedStatement.setInt(3, randomScore());
      preparedStatement.addBatch();
}
preparedStatement.executeBatch();
connection.commit();
preparedStatement.clearBatch();

最终用时0.2秒,终极方法。 所以建议在处理大批量的数据时,同时使用批处理和事务。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值