JDBC知识点/第四部分高效的批量操作
写在前面:本博客是JDBC第四部分,JDBC学习路线目录为:
JDBC总目录
欢迎大家一起讨论,如有错误,敬请指正
4 高效的批量插入
- 为什么说是批量插入:因为update和delete本身就是具有批量操作的性质(
WHERE id<?
) - 下面方式一到方式四效率逐渐提高!!!!
4.1 方式一
- 使用
Statement
进行批量插入:思路使用for循环来依次插入
/*插入两千条数据到person表*/
public void mode1() throws SQLException {
Connection conn = JDBCUtils.getConnection();
Statement st = conn.createStatement();
for (int i = 1; i <= 20000 ; i++) {
String sql = "INSERT INTO person(name)values('name_"+i+"')";
st.execute(sql);
}
}
执行时间大概是5秒左右
4.2 方式二
- 既然有
Statement
肯定有PrepareStatement
/*插入两千条数据到person表*/
public void mode2(){
Connection conn = null;
PreparedStatement ps = null;
try{
conn = JDBCUtils.getConnection();
String sql = "INSERT INTO person(name)values(?)";
ps = conn.prepareStatement(sql);
for (int i = 1; i <= 20000 ; i++) {
ps.setObject(1,"name_" + i);
ps.execute();
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn,ps);
}
}
- 经过测试,同样是插入2000条数据,
PrepareStatement
的效率大概是Statement
的五倍
4.3 方式三
- 观察上方代码,我们是否有办法进行优化,使效率提高?
- 从上方代码中(
ps.setObject(1,"name_" + i); ps.execute();
)我们可以看出,每次进行插入操作都需要进行一次执行操作,而连接数据库进行执行是比较消耗时间的,那么我们是否可以将要插入的数据先进行缓存到一定数目再执行插入呢?答案是可以的,但是我们需要引入几个新的方法:
addBatch()
:缓存SQL语句executeBatch()
:执行缓存的SQL语句clearBatch()
:清除缓存的SQL语句- 注意事项:默认情况MySql不支持批处理,需要更改配置文件,添加语句:
rewriteBatchedStatements=true
(例:jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
)同时驱动需要更新至JDBC3.0及以上版本
/*插入两万条数据到person表*/
public void mode3(){
Connection conn = null;
PreparedStatement ps = null;
try{
conn = JDBCUtils.getConnection();
String sql = "INSERT INTO person(name)values(?)";
ps = conn.prepareStatement(sql);
for (int i = 1; i <= 20000 ; i++) {
ps.setObject(1,"name_" + i);
//储存sql语句
ps.addBatch();
//一定条件进行执行
if(i%500 == 0){
//执行
ps.executeBatch();
//清空
ps.clearBatch();
}
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn,ps);
}
}
4.4 方式四
- 最后的终极优化!
- 因为在JDBC中,数据的提交方式默认是自动提交,这也在一定程度上影响效率,所以我们在执行插入之前将数据提交设置为手动即可。
- 注意事项:一定要在数据处理结束后将自动提交设置回自动,否则可能影响其他操作!!!
/**
* 通过设置数据不允许自动提交来实现提高效率
*/
public void mode4(){
Connection conn = null;
PreparedStatement ps = null;
try{
conn = JDBCUtils.getConnection();
//设置数据不允许自动提交数据
conn.setAutoCommit(false);
String sql = "INSERT INTO person(name)values(?)";
ps = conn.prepareStatement(sql);
for (int i = 1; i <= 20000 ; i++) {
ps.setObject(1,"name_" + i);
//缓存sql语句
ps.addBatch();
//一定条件进行执行
if(i%500 == 0){
//执行
ps.executeBatch();
//清空
ps.clearBatch();
}
}
//提交数据
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//设置为自动提交
conn.setAutoCommit(true);
JDBCUtils.closeResource(conn,ps);
}
}