关于批量插入数据之我见(100万级别的数据,mysql)
因前段时间去面试,问到怎样高效向数据库插入10万条记录,之前没处理过类似问题。也没看过相关资料,结果没答上来,今天就查了些资料。总结出三种方法:
測试数据库为mysql!!!
方法一:
public static void insert() {
		// 开时时间
		Long begin = new Date().getTime();
		// sql前缀
		String prefix = "INSERT INTO tb_big_data (count, create_time, random) VALUES ";
		try {
			// 保存sql后缀
			StringBuffer suffix = new StringBuffer();
			// 设置事务为非自己主动提交
			conn.setAutoCommit(false);
			// Statement st = conn.createStatement();
			// 比起st,pst会更好些
			PreparedStatement pst = conn.prepareStatement("");
			// 外层循环,总提交事务次数
			for (int i = 1; i <= 100; i++) {
				// 第次提交步长
				for (int j = 1; j <= 10000; j++) {
					// 构建sql后缀
					suffix.append("(" + j * i + ", SYSDATE(), " + i * j
							* Math.random() + "),");
				}
				// 构建完整sql
				String sql = prefix + suffix.substring(0, suffix.length() - 1);
				// 加入运行sql
				pst.addBatch(sql);
				// 运行操作
				pst.executeBatch();
				// 提交事务
				conn.commit();
				// 清空上一次加入的数据
				suffix = new StringBuffer();
			}
			// 头等连接
			pst.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		// 结束时间
		Long end = new Date().getTime();
		// 耗时
		System.out.println("cast : " + (end - begin) / 1000 + " ms");
	}
输出时间:cast : 23 ms
该方法眼下測试是效率最高的方法!
方法二:
public static void insertRelease() {
		Long begin = new Date().getTime();
		String sql = "INSERT INTO tb_big_data (count, create_time, random) VALUES (?, SYSDATE(), ?)";
		try {
			conn.setAutoCommit(false);
			PreparedStatement pst = conn.prepareStatement(sql);
			for (int i = 1; i <= 100; i++) {
				for (int k = 1; k <= 10000; k++) {
					pst.setLong(1, k * i);
					pst.setLong(2, k * i);
					pst.addBatch();
				}
				pst.executeBatch();
				conn.commit();
			}
			pst.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		Long end = new Date().getTime();
		System.out.println("cast : " + (end - begin) / 1000 + " ms");
	}
注:凝视就没有了,和上面类同,以下会有分析!
控制台输出:cast : 111 ms
运行时间是上面方法的5倍!
方法三:
public static void insertBigData(SpringBatchHandler sbh) {
		Long begin = new Date().getTime();
		JdbcTemplate jdbcTemplate = sbh.getJdbcTemplate();
		final int count = 10000;
		String sql = "INSERT INTO tb_big_data (count, create_time, random) VALUES (?, SYSDATE(), ?)";
		jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
			// 为prepared statement设置參数。这种方法将在整个过程中被调用的次数
			public void setValues(PreparedStatement pst, int i)
					throws SQLException {
				pst.setLong(1, i);
				pst.setInt(2, i);
			}
			// 返回更新的结果集条数
			public int getBatchSize() {
				return count;
			}
		});
		Long end = new Date().getTime();
		System.out.println("cast : " + (end - begin) / 1000 + " ms");
	}
该方法採用的是spring batchUpdate运行。因效率问题,数据量仅仅有1万条!
运行时间:cast : 387 ms
总结:方法一和方法二非常类同,唯一不同的是方法一採用的是“insert into tb (...) values(...),(...)...;”的方式运行插入操作,
方法二则是“insert into tb (...) values (...);insert into tb (...) values (...);...”的方式,要不是測试,我也不知道两者区别是如此之大!
当然,这个仅仅是眼下的測试,详细运行时间和步长也有非常大关系!如过把步长改为100,可能方法就要几分钟了吧。这个能够自己測试哈。。
。
方法三网上非常推崇,只是,效率大家也都看到了,1万条记录。耗时6分钟。可见其效率并不理想!并且方法三须要配置spring applicationContext环境才干应用!
只是,方法三在ssh/spring-mvc中可用性还是非常高的!
刚才開始研究大数据方面的问题。以上也仅仅是真实測试的结果,并不一定就是事实,有好的建议。大家请指正。谢谢!
相互学习,才干进步更快。
晚点会把源代码发上来。大家能够直接去下载測试!
 
                    
                     
                    
                 
                    
                 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号