最近公司要求测试数据库的性能,就上网查了一些批量插入数据的代码,发现有好几种不同的用法,插入同样数据的耗时也有区别
别的先不说,先上一段代码与君共享
方法一:
package com.bigdata; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.PreparedStatement; public class TestBigData { /** * @param args * @throws Exception * @throws IllegalAccessException * @throws InstantiationException */ public static void main(String[] args) throws Exception { //--------------------------------连接数据库---------------------- String driver="com.mysql.jdbc.Driver"; String url="jdbc:mysql://127.0.0.1:3306/test"; String user="root"; String password="root"; //1、新建驱动 Driver driverInstance = (Driver) Class.forName(driver).newInstance(); //2、注册驱动 DriverManager.registerDriver(driverInstance); //3、获取连接 Connection conn = DriverManager.getConnection(url, user, password); //----------------------对数据库进行操作------------------- //记录开始时间 Long begin=System.currentTimeMillis(); //-----------插入数据---------- //sql语句前缀 String sqlPre="insert into tb_big_db (count,create_time,random) values "; StringBuffer sb = new StringBuffer(); //设置事务为非自动提交 conn.setAutoCommit(false); //使用PrepareStatement更好 PreparedStatement pstate = conn.prepareStatement(""); //--------------------------十万条数据------------- //设置外循环,总提交事务的次数 for(int i=0;i<100;i++){ for(int j=0;j<10000;j++){ //构建sql后缀 sb.append("("+j*i+",SYSDATE(),"+i*j*Math.random()+"),"); } //构建完整的sql String sql = sqlPre + sb.substring(0, sb.length()-1); //添加sql pstate.addBatch(sql); //执行sql pstate.executeBatch(); //提交事务 conn.commit(); //清空StringBuffer上一次添加的sql语句 sb = new StringBuffer(); } //大循环完毕,关闭连接 pstate.close(); conn.close(); //结束时间 Long end = System.currentTimeMillis(); System.out.println("10万条数据,插入数据库耗时:"+(end-begin)+"ms"); } }
耗时:1952ms
说明:这速度,不堪入目啊,公司的数据库,不管从硬件还是软件来看,都不行呐。
方法二:
package com.bigdata; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.PreparedStatement; public class TestBigData2 { public static void main(String[] args) throws Exception{ //--------------------------------连接数据库---------------------- String driver="com.mysql.jdbc.Driver"; String url="jdbc:mysql://127.0.0.1:3306/test"; String user="root"; String password="root"; //1、新建驱动 Driver driverInstance = (Driver) Class.forName(driver).newInstance(); //2、注册驱动 DriverManager.registerDriver(driverInstance); //3、获取连接 Connection conn = DriverManager.getConnection(url, user, password); //-----------------------------------操作数据库----------------- //记录开始时间 Long begin = System.currentTimeMillis(); //动态sql语句 String sql = "insert into tb_big_db (count,create_time,random) values (?,SYSDATE(),?)"; //设置事务为非自动提交 conn.setAutoCommit(false); //预编译sql PreparedStatement pstate = conn.prepareStatement(sql); //外循环10次 for(int i=0;i<10;i++){ //内循环10000次 for(int j=0;i<1000;j++){ pstate.setLong(1, i*j); pstate.setLong(2, i*j); //添加到批处理上 pstate.addBatch(); } //批处理 pstate.executeBatch(); //提交 conn.commit(); } //关闭 pstate.close(); conn.close(); //结束时间 Long end = System.currentTimeMillis(); System.out.println("插入10万条数据,耗时:"+(end-begin)+"ms"); } }
耗时:未知,原因是我用这个方法测试的时候,居然给我报内存溢出异常,说明这个方法需要的内存大,耗时高,所以我和上面的方法一做了个对比。
由于2个方法都用来prepareStatement类,该类在执行sql语句之前会对其进行预编译,就是说先把sql准备好先,用到的时候就直接用就可以了
方法一:通过代码分析,可以明显看到,方法一种的sql语句通过拼接成10条sql语句,故数据库执行语句时,只要执行10条就好
方法二:可以看出,它每循环一次,就要addBach()一次,速度变得更加慢,有10000条就addBatch()一万次,再批处理10次,所以速度变得慢是理所当然的