数据仓库系列 之使用PreparedStatement执行批量插入sql的三种方式
Posted 琅晓琳
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据仓库系列 之使用PreparedStatement执行批量插入sql的三种方式相关的知识,希望对你有一定的参考价值。
使用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);
三种方式的效率依次递进,当然具体情况还是要分具体应用场景来看。
补充:
关于rewriteBatchedStatements这个参数介绍:
MySQL的JDBC连接的url中要加rewriteBatchedStatements参数,并保证5.1.13以上版本的驱动,才能实现高性能的批量插入。
MySQL JDBC驱动在默认情况下会无视executeBatch()语句,把我们期望批量执行的一组sql语句拆散,一条一条地发给MySQL数据库,批量插入实际上是单条插入,直接造成较低的性能。
只有把rewriteBatchedStatements参数置为true, 驱动才会帮你批量执行SQL。
另外这个选项对INSERT/UPDATE/DELETE都有效。
参考资料:
https://blog.csdn.net/weixin_45861045/article/details/126095061 使用PreparedStatement执行批量插入sql的三种方式以及效率
https://blog.csdn.net/qq_34283987/article/details/107694587 批处理 rewriteBatchedStatements=true
以上是关于数据仓库系列 之使用PreparedStatement执行批量插入sql的三种方式的主要内容,如果未能解决你的问题,请参考以下文章
数据仓库系列 之使用PreparedStatement执行批量插入sql的三种方式