批处理: 对数据进行批量处理,尤其是对同一张表反复进行的大量数据新增、修改、删除操作;
问题描述:
BatchSample:tc1()方法未采用批处理;tc2()方法采用了批处理。
package com.imooc.jdbc.sample;
import com.imooc.jdbc.common.DbUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Date;
/**
* JDBC批处理
*/
public class BatchSample {
// 标准使用方式:未使用批处理的方法
private static void tc1(){
Connection conn = null;
PreparedStatement pstmt = null;
try {
long startTime = new Date().getTime(); // 开始时间,统计时间之用;
conn = DbUtils.getConnection();
conn.setAutoCommit(false); // 关闭自动提交;
String sql = "insert into employee(eno,ename,salary,dname) values(?,?,?,?)";
for (int i = 100000; i < 200000; i++) {
if (i == 4005) {
//throw new RuntimeException("插入失败");
}
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, i);
pstmt.setString(2, "员工" + i);
pstmt.setFloat(3, 4000);
pstmt.setString(4, "市场部");
pstmt.executeUpdate();
}
conn.commit();//提交数据
long endTime = new Date().getTime(); // 结束时间,统计时间之用;
System.out.println("tc1()方法,未使用批处理的时间为:"+(endTime-startTime));
}catch (Exception e) { //一旦上面在执行的过程中,抛出里异常;在catch块中,必须要对其进行捕捉;
e.printStackTrace();
try {
if (conn != null && conn.isClosed() == false) {
conn.rollback(); //数据回滚
}
} catch (SQLException ex) {
ex.printStackTrace();
}
} finally {
DbUtils.closeConnection(null, pstmt, conn);
}
}
/**
* 使用批处理的方式
*/
private static void tc2(){
Connection conn = null;
PreparedStatement pstmt = null;
try {
long startTime = new Date().getTime(); // 开始时间,统计时间之用;
conn = DbUtils.getConnection();
conn.setAutoCommit(false); // 关闭自动提交;
String sql = "insert into employee(eno,ename,salary,dname) values(?,?,?,?)";
pstmt = conn.prepareStatement(sql);
for (int i = 200000; i < 300000; i++) {
if (i == 4005) {
//throw new RuntimeException("插入失败");
}
pstmt.setInt(1, i);
pstmt.setString(2, "员工" + i);
pstmt.setFloat(3, 4000);
pstmt.setString(4, "市场部");
//pstmt.executeUpdate();
//将【i,员工+i,4000,市场部】四个参数添加到当前的prepareStatement的批处理任务中。
//这儿只是添加任务,并不是执行;
pstmt.addBatch();
}
// 执行批处理任务;通过这一句话,就可以将刚才的100000个批处理任务一次性打包发送到MySQL,
// MySQL再对这100000条数据一次性执行插入的操作;
pstmt.executeBatch();
conn.commit();//提交数据
long endTime = new Date().getTime(); // 结束时间,统计时间之用;
System.out.println("tc2()方法,使用批处理的时间为:"+(endTime-startTime));
}catch (Exception e) { //一旦上面在执行的过程中,抛出里异常;在catch块中,必须要对其进行捕捉;
e.printStackTrace();
try {
if (conn != null && conn.isClosed() == false) {
conn.rollback(); //数据回滚
}
} catch (SQLException ex) {
ex.printStackTrace();
}
} finally {
DbUtils.closeConnection(null, pstmt, conn);
}
}
public static void main(String[] args) {
tc1();
tc2();
}
}
BatchSample类几点说明:
(1) tc1()方法是未使用批处理的策略;tc2()是使用批处理的策略;
(2) tc1()和tc2()分析
tc1()方法:每条prepareStatement对象只新增一条数据,通过创建100000条prepareStatement对象来新增100000条数据;
tc2()方法:用一个prepareStatement对象去新增100000条数据;
(3)批处理的实现策略:
运行结果:
分析:
(1)其一,实例化prepareStatement对象是需要时间的,tc1()实例化了10000次,而tc2()只实例化了1次;
(2)其二,tc1()每循环一次,都要把sql语句发送到MySQL解析执行,每一次都要解析,MySQL需要解析100000次;
**tc2(),只需要发送一条sql语句并附带100000组参数,一起交给MySQL批量执行;这样的方法会快很多;**
(3)当sql语句越长,解析的难度越大,利用批处理的优势会更明显。所以,上面执行效率提高30%是很保守的。