日期:2014-05-16  浏览次数:20748 次

MySql批量插入数据
   在实际的开发过程中,特别是大型的分布式应用系统,往往会涉及到大批量的数据。那么在测试的时候就需要准备足够多的数据以便进行测试。
   为了提高插入数据的效率,我们可以利用MySql的批量插入数据能力。其实,从本质来说也就是取消JDBC中事务的自动提交,改为手动提交。
   如果没有关闭JDBC事务的自动提交,那么JDBC驱动会在每次执行了一条SQL语句之后,自动提交,并且关闭连接。而我们知道打开数据库连接是非常耗资源的,而且有些JDBC框架还会限制数据库操作的频率。这种情况下,如果采用单调数据插入效果非常不好。
   解决的方法之一,就是关闭JDBC事务的自动提交,改为手动提交。我们可以记录SQL语句的执行次数,然后当达到某一个值的时候,比如10w次的时候,手动提交一下事务,然后关闭并重新开始数据库连接。再进行下一批数据局的插入或者更新。
   这种方法非常适合于准备测试环境当中的大批量数据。在运行程序过程中,会碰到JVM抛出内存不足的异常,这个时候可以调大内存,或者减少每批数据的数据量来解决。
   以下代码仅供参考,在下面代码中,每批的数据库量为1w条记录。不同JDBC版本支持的批量插入的数据量不同,为了谨慎起见,可以先改小一点,然后慢慢提高。
@Test
	public void testInsertFollowRelation(){
		String db = "com.mysql.jdbc.Driver";
		String host = "jdbc:mysql://127.0.0.1:3306/test?characterEncoding=GBK";
		String user = "abc";
		String passwd = "abc";
		Connection con = null; 
		
		try{
			Class.forName(db).newInstance(); 
		} catch (Exception e) {
			System.out.println("加载驱动失败:" + db);
		} 
		
		long starTime = System.currentTimeMillis();
		try { 
                        long startRowNum = 0;
			long count = 0;
			//使用事务插入,每10000条数据提交一下事务。
			//提高效率
			for(int i = 0; i < 10; i++){
				BufferedReader reader = new BufferedReader(new FileReader(new File("E:\\test.txt")));
				con = DriverManager.getConnection(host, user, passwd); 
				con.setAutoCommit(false);
				PreparedStatement pstmt = con.prepareStatement("INSERT INTO test " +
						"(id,info) " +
						"VALUES(?,?,?,now())"); 
                                String info = null;
				while((info= reader.readLine()) != null){
					pstmt.setLong(1, startRowNum);
					pstmt.setLong(2, info);
					
					pstmt.executeUpdate();
					count++;
                                        startRowNum ++;
					if(startRowNum % 10000 == 0){//如果数据条数达到10000条,则提交事务
						con.commit();
						con.close();
						//重开链接
						con = DriverManager.getConnection(host, user, passwd); 
						con.setAutoCommit(false);
						pstmt = con.prepareStatement("INSERT INTO test " +
						"(id,info) " +
						"VALUES(?,?,?,now())"); 
						
						System.out.println("数据量达到10000条,提交事务完成。");
					}
				}
				
				reader.close();
			}
			long endTime = System.currentTimeMillis();
			System.out.println("共耗时:<" + new Float(((endTime-starTime)/1000)) + ">秒。插入了(" + count + ")条数据");
		} catch(Exception e){
			e.printStackTrace();
			try {
				con.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		}
	}
1 楼 a283037321 2012-09-20  
(startRowNum % 10000 == 0  这样如果数据总数取余后不等于0则后面剩下了少于1000条的数据没有插入数据库吧?
2 楼 a283037321 2012-09-20  
while((info= reader.readLine()) != null){ 
                    pstmt.setLong(1, startRowNum); 
                    pstmt.setLong(2, info);                     
                    count++; 
                    pstmt.addBatch();
                                        startRowNum ++;