批量操作
导读
-
预编译优势 DBServer会对预编译语句提供性能优化。因为预编译语句有可能被重复调用,所以语句在被DBServer的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不与要再编译,只要将参数直接传入编译过的语句中就会得到执行。 -
Statement语句中,无法进行预编译,每次执行sql语句,都会进行语法检查、语义检查、再翻译成二进制命令、缓存等操作,对于批量操作极为浪费资源 -
Batch方法及将AutoCommit的默认值设为false,都是为了减少PerparedStatement与数据库的交互次数
一、批量操作层次一
-
使用Statement,没有预编译,会进行多次次的语法检查等操作,效率低 -
插入20,000条数据所用时间为:22189ms @Test
public void testStatement() {
Long start = System.currentTimeMillis();
Connection conn = null;
Statement st = null;
try {
conn = JdbcUtils.getConnection();
st = conn.createStatement();
for (int i = 0; i < 20000; i++) {
String sql = "insert into customers(cust_name) values('name_" + i + "')";
st.execute(sql);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtils.closeResource(conn,st);
}
Long end = System.currentTimeMillis();
System.out.println("Statement插入20000条数据所用时间为:" + (end - start));
}
二、批量操作层次二
-
使用PreparedStatement,可以进行预编译,不用重复进行语法检查、语义检查等操作,但仍然需要和数据库进行N次交互 -
插入20,000条数据操作所需时间:22164ms @Test
public void testPreparedStatement2() {
Long start = System.currentTimeMillis();
Connection conn = null;
PreparedStatement ps = null;
try {
conn = JdbcUtils.getConnection();
String sql = "insert into customers(cust_name) values(?)";
ps = conn.prepareStatement(sql);
for (int i = 0; i < 20000; i++) {
ps.setObject(1,"name_" + i);
ps.execute();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtils.closeResource(conn,ps);
}
Long end = System.currentTimeMillis();
System.out.println("PreparedStatement普通预编译执行插入20000条数据操作所需时间:" + (end - start));
}
三、批量操作层次三
-
PreparedStatement使用了addBatch()、executeBatch()、clearBatch()方法,可以形成一定的执行缓存,减少与数据库的交互,极大提升效率 -
需要在配置文件jdbc.properties中,在url字符串后增加 ?rewriteBatchedStatements=true ,确使Batch方法可用,jar包需在5.1.37之上 -
插入20,000条数据的时间为359ms @Test
public void testPreparedStatement3() {
Long start = System.currentTimeMillis();
Connection conn = null;
PreparedStatement ps = null;
try {
conn = JdbcUtils.getConnection();
String sql = "insert into customers(cust_name) values(?)";
ps = conn.prepareStatement(sql);
for (int i = 0; i < 1000000; i++) {
ps.setObject(1,"name_" + i);
ps.addBatch();
if (i % 500 == 0) {
ps.executeBatch();
ps.clearBatch();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtils.closeResource(conn,ps);
}
Long end = System.currentTimeMillis();
System.out.println("PreparedStatement使用Batch执行插入20000条数据操作所需时间:" + (end - start));
}
四、批量操作层次四
-
则使用Batch的基础上,将自动提交AutoCommit的默认值设置为false,使ps与数据库的交互只有一次,则效率就更高了 -
DML的提交及回顾问题参考博文:MySQL十: DDL (数据库/数据表的增、查、改、删) -
插入1,000,000条数据使用时间为5345ms @Test
public void testPreparedStatement4() {
Long start = System.currentTimeMillis();
Connection conn = null;
PreparedStatement ps = null;
try {
conn = JdbcUtils.getConnection();
conn.setAutoCommit(false);
String sql = "insert into customers(cust_name) values(?)";
ps = conn.prepareStatement(sql);
for (int i = 0; i < 1000000; i++) {
ps.setObject(1,"name_" + i);
ps.addBatch();
if (i % 500 == 0) {
ps.executeBatch();
ps.clearBatch();
}
}
conn.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtils.closeResource(conn,ps);
}
Long end = System.currentTimeMillis();
System.out.println("PreparedStatement更改commit后执行插入1000000条数据操作所需时间:" + (end - start));
}
|