使用PreparedStatement(方式一):
@Test
public void test1() {
Connection conn = null;
PreparedStatement ps = null;
try {
long start = System.currentTimeMillis();
conn = DBUtil.getConnection();
String sql = "insert into table1(`name`) values(?)";
ps = conn.prepareStatement(sql);
for (int i = 1; i <= 20000; i++) {
ps.setString(1, "name_" + i);
ps.execute();
}
long end = System.currentTimeMillis();
System.out.println("执行20000条sql共花费" + (end - start) + "毫秒");
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtil.CloseDB(conn, ps);
}
}
使用PreparedStatement相较于Statement在批量插入上的优点:不用每次都去编译sql语句。
使用PreparedStatement的方式二:使用了 addBatch() / executeBatch() / clearBatch()三板斧,batch类似缓冲池,可以先攒一定数量的sql,数量到了我们指定batch的大小然后再批量执行。代码如下:
/*
* 修改1: 使用 addBatch() / executeBatch() / clearBatch()
* 修改2:mysql服务器默认是关闭批处理的,我们需要通过一个参数,让mysql开启批处理的支持。
* ?rewriteBatchedStatements=true 写在配置文件的url后面
* 修改3:使用更新的mysql 驱动:mysql-connector-java-5.1.37-bin.jar
*
*/
@Test
public void test2() {
Connection conn = null;
PreparedStatement ps = null;
try {
long start = System.currentTimeMillis();
conn = DBUtil.getConnection();
String sql = "insert into table1(`name`) values(?)";
ps = conn.prepareStatement(sql);
for (int i = 1; i <= 10000000; i++) {
ps.setString(1, "name_" + i);
//ps.execute();
//1.“攒”sql
ps.addBatch();
if (i % 500 == 0) {
//2.执行Batch
ps.executeBatch();
//3.清空Batch
ps.clearBatch();
}
}
long end = System.currentTimeMillis();
System.out.println("执行一千万条sql共花费" + (end - start) + "毫秒");
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtil.CloseDB(conn, ps);
}
}
使用PreparedStatement的方式三:使用batch批量处理的前提下,设置手动提交,因为每次执行executeBatch会自动提交一次,这里也会涉及与数据库的交互,需要耗费一定的时间,因此我们可以设置手动提交,等执行完所有要批量插入的数据后在手动提交。代码如下:
@Test
public void test3() {
Connection conn = null;
PreparedStatement ps = null;
try {
long start = System.currentTimeMillis();
conn = DBUtil.getConnection();
//设置为手动提交数据
conn.setAutoCommit(false);
String sql = "insert into table1(`name`) values(?)";
ps = conn.prepareStatement(sql);
for (int i = 1; i <= 10000000; i++) {
ps.setString(1, "name_" + i);
//ps.execute();
//1.“攒”sql
ps.addBatch();
if (i % 500 == 0) {
//2.执行Batch
ps.executeBatch();
//3.清空Batch
ps.clearBatch();
}
}
//提交数据
conn.commit();
long end = System.currentTimeMillis();
System.out.println("执行一千万条sql共花费" + (end - start) + "毫秒");
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtil.CloseDB(conn, ps);
}
}
三种使用PreparedStatement的方式进行效率比较如下:
方式一和方式二同时插入2万条数据对比如下:
方式二和方式三同时插入1千万条数据的效率对比如下:
综上所述,三种方式的效率依次递进,当然具体情况还是要分具体应用场景来看。