添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Oracle:高效批量插入数据

声明:这不是教程,只是个小结。不适用于生产环境,仅属于实验性质的设定。

环境:JDK8,Oracle 11g

机器:Lenovo Y50,8G内存,512G硬盘,i5处理器

结论:18个字段,插入100万条数据,耗时20~30s。


Java部分:

1,使用的jar包是ojdbc6.jar

2,关闭自动提交

3,使用Connection.prepareStatement()预编译SQL语句,对于一个批次的数据而言,只需要编译一次即可。

4,对于每一条数据,在将参数设置到PreparedStatement对象之后,使用PreparedStatement.addBatch()方法添加到批次中。

5,每添加1000条数据,执行1次PreparedStatement.executeBatch()方法。

6,全部执行完毕后,手动一次性提交。

代码示例:

public void testA1_SetInsertParameters() {
	System.out.println();
	System.out.println(">>>Test1SchemaTest->testA1_SetInsertParameters()");
	Connection conn = null;
	PreparedStatement ps = null;
	int count = 1000000;
	try {
		// 获取连接
		conn = JdbcPool.getConnection();
		// 关闭自动提交
		conn.setAutoCommit(false);
		// 清空测试表
		String deleteSql = "truncate table test1";
		ps = conn.prepareStatement(deleteSql);
		ps.execute();
		conn.commit();
		ps.close();
		long startTime = System.currentTimeMillis();
		// 获取插入语句SQL
		 insert into test1 (my_binary_double, my_binary_float, my_blob, my_clob, my_char, 
		 my_date, my_interval_day_to_second_, my_interval_year_to_month, my_long, my_nclob, 
		 my_number, my_nvarchar2, my_raw, my_timestamp_with_local, my_timestamp_with_time_zone, 
		 my_timestamp, my_integer, my_varchar2) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 
		 ?, ?, ?, ?, ?, ?)
		String sql = new Test1Schema().insertSql();
		// 预编译插入语句
		ps = conn.prepareStatement(sql);
		for (int i = 0; i < count; i++) {
			Test1Schema test1Schema = new Test1Schema();
			test1Schema.setMyNumber(Double.valueOf(i));
			test1Schema.setMyNvarchar2("A");
			test1Schema.setMyChar("ZZZ");
			test1Schema.setMyBinaryDouble(1.1d);
			test1Schema.setMyBinaryFloat(2.2d);
			test1Schema.setMyDate(Utility.getCurrentDate());
			test1Schema.setMyInteger(10);
			test1Schema.setMyLong("VVVV");
			test1Schema.setMyTimestamp(Utility.getCurrentTimeStamp());
			test1Schema.setMyTimestampWithLocal(Utility.getCurrentTimeStamp());
			test1Schema.setMyTimestampWithTimeZone(Utility.getCurrentTimeStamp());
			test1Schema.setMyVarchar2("UU");
			// 将参数传递给PreparedStatement
			test1Schema.insertParameters(ps);
			if ((i + 1) % 1000 == 0) {
				// 执行批次
				ps.executeBatch();
				// 清空批次
				ps.clearBatch();
		// 执行最后的不足1000条数据的批次
		ps.executeBatch();
		// 提交
		conn.commit();
		long endTime = System.currentTimeMillis();
		System.out.println("测试插入" + count + "条用时:" + 
			String.format("%.2f", (double) (endTime - startTime) / 1000) + "秒");
	} catch (SQLException e1) {
		e1.printStackTrace();
		fail();
	} finally {
		try {
			if (ps != null) {
				ps.close();
			if (conn != null) {
				conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
			fail();
}

代码示例:

/** 为经过预编译的ps设置插入语句的参数 */
public boolean insertParameters(PreparedStatement ps) {
	if (!checkNotNullKey() || ps == null) {
		return false;
	try {
		if (this.myBinaryDouble == null) {
			ps.setNull(1, 8);
		} else {
			ps.setDouble(1, this.myBinaryDouble);
		// 略......
		if (this.myVarchar2 == null) {
			ps.setNull(18, 12);
		} else {
			ps.setString(18, this.myVarchar2);
		ps.addBatch();