在jdbc2.0里增加了批量处理的功能(batch),其允许将多个sql语句作为一个单元送至数据库去执行,这样做可以提高操作效率。在操作大量的数据时, ORM框架实现批量是很慢的。我们可以使用jdbc提供的Batch来提高效率。
示例:
首先是使用for循环,一句一句的执行:
public class TestCommon { static long startTime; public static void main(String[] args) throws Exception { Connection conn = getConnection(); PreparedStatement ps = null; try { startTime=System.nanoTime(); //获取开始时间 ps = conn .prepareStatement("INSERT INTO batchtab values (?, ?)"); conn.setAutoCommit(false); for (int n = 0; n < 10000; n++) { Integer i = new Integer(n); ps.setString(1, i.toString()); ps.setString(2, "value" + i.toString()); ps.executeUpdate(); } conn.commit(); long endTime=System.nanoTime(); //获取结束时间 System.out.println("程序运行时间: "+(endTime-startTime)+"ns"); }catch (SQLException ex) { System.out.println("SQLException: " + ex.getMessage()); System.out.println("SQLState: " + ex.getSQLState()); System.out.println("Message: " + ex.getMessage()); System.out.println("Vendor error code: " + ex.getErrorCode()); } catch (Exception e) { e.printStackTrace(); System.err.println("Exception: " + e.getMessage()); } finally { if (conn != null) conn.close(); if (ps != null) ps.close(); } } public static Connection getConnection() { Connection con = null; //创建用于连接数据库的Connection对象 try { Class.forName("com.mysql.jdbc.Driver");// 加载Mysql数据驱动 con = DriverManager.getConnection( "jdbc:mysql://localhost:3306/TestBatch", "root", "123456");// 创建数据连接 } catch (Exception e) { System.out.println("数据库连接失败" + e.getMessage()); } return con; //返回所建立的数据库连接 } }
使用Batch,批量操作:
public class TestPreStatementBatch { static long startTime; public static void main(String[] args) throws Exception { Connection conn = getConnection(); ResultSet rs = null; PreparedStatement ps=null; try { startTime=System.nanoTime(); //获取开始时间 ps = conn.prepareStatement("INSERT INTO batchtab values (?, ?)"); conn.setAutoCommit(false); ps.clearBatch(); for (int n=0; n<10000; n++) { Integer i = new Integer(n); ps.setString(1, i.toString()); ps.setString(2, "value" + i.toString()); ps.addBatch(); } ps.executeBatch(); conn.commit(); long endTime=System.nanoTime(); //获取结束时间 //打印消耗时间 System.out.println("程序运行时间: "+(endTime-startTime)+"ns"); } catch (BatchUpdateException b) { System.out.println("SQLException: " + b.getMessage()); System.out.println("SQLState: " + b.getSQLState()); System.out.println("Message: " + b.getMessage()); System.out.println("Vendor error code: " + b.getErrorCode()); System.out.print("Update counts: "); } catch (SQLException ex) { System.out.println("SQLException: " + ex.getMessage()); System.out.println("SQLState: " + ex.getSQLState()); System.out.println("Message: " + ex.getMessage()); System.out.println("Vendor error code: " + ex.getErrorCode()); } catch (Exception e) { e.printStackTrace(); System.err.println("Exception: " + e.getMessage()); } finally { if( conn != null ) conn.close(); if(ps !=null) ps.close(); if(rs !=null) rs.close(); } } public static Connection getConnection() { Connection con = null; //创建用于连接数据库的Connection对象 try { Class.forName("com.mysql.jdbc.Driver");// 加载Mysql数据驱动 con = DriverManager.getConnection( "jdbc:mysql://localhost:3306/TestBatch", "root", "123456");// 创建数据连接 } catch (Exception e) { System.out.println("数据库连接失败" + e.getMessage()); } return con; //返回所建立的数据库连接 } }
不同点:
一条条的循环插入是每插入一条数据都会调用一次执行;而Batch是把所有的数据全都存起来,之后调用一次执行。数据量很大的话,效率就会差很多。
数据说话——运行结果:
总结:
通过插入一万条一样的数据消耗的时间,我们可以看到相差的时间。我们可以通过减少语句的多次执行来提高性能。其实,同.NET中的SqlBulkCopy思想一样,一次执行WriteToServer。就如同生活中我们做事情一样,不能只想做了就行,还要多多思考有没有什么方法可以做到更好。