[JDBC]批量提交插入语句以提高数据插入速度(效率提升不明显)

// Initialize conn&stmt
Connection conn=null;
Statement stmt=null;

...

conn=dataSource.getConnection();
stmt = conn.createStatement();

...

conn.setAutoCommit(false);
stmt = conn.createStatement();

for(int i=0;i<recordCount;i++) {
    String insertSql=getInsertSql(tableName,typefields,currTime,i);
    stmt.addBatch(insertSql);
    currTime=timePastNSecond(currTime,nSeconds);
    
    if( (i!=0) && (i % 1000==0) ) { // 这里控制壹千条插入语句一提交
        stmt.executeBatch();
        stmt.clearBatch();
        conn.commit();
        logger.info("."+index+" 1000 records have been inserted to table:'"+tableName+"'.");
    }
}

// 最后再提交一次
stmt.executeBatch();
stmt.clearBatch();
conn.commit();

这个方法试下来,在我遇到的Oracle(Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production )上, 插入638万条数据(两张大表一个三百万,其余19张小表每张两万)花费9小时多,而之前的插入语句(一条insert一提交)插入419万条数据(两张大表一个二百万,其余19张小表每张一万)花费6个半小时,感觉提升并不明显。当然,我得到的sql语句因为表不一样造成Insert语句不一致,可能也是效率提升不明显的原因。

我的原有方案是这样写的:

conn.setAutoCommit(false);
                    
for(int i=0;i<recordCount;i++) {
    StringBuilder sb=new StringBuilder();
    sb.append("insert into "+tableName+"(");
    List<String> fields=new ArrayList<String>();
    for(TypeField tf:typefields) {
        fields.add(tf.field);
    }
    sb.append(String.join(",",fields));
    
    sb.append(") values(");
    List<String> values=new ArrayList<String>();
    for(TypeField tf:typefields) {
        if(tf.type.equals("PK")) {
            if(tableName.equals("DELIVERY_INFO_HISTORY")) {
                values.add("'0'");
            }else {
                values.add("'"+String.valueOf(i)+"'");
            }
        }else if(tf.type.equals("CH")) {
            values.add("'0'");
        }else if(tf.type.equals("DT")) {
            values.add("to_date('"+currTime+"','yyyy-MM-dd HH24:mi:ss')");
        }else if(tf.type.equals("US")) {
            values.add("'UserABC'");
        }
    }
    sb.append(String.join(",",values));
    sb.append(")");
    
    String insertSql=sb.toString();
    
    insertedActual+=stmt.executeUpdate(insertSql); 
    
    currTime=timePastNSecond(currTime,nSeconds);
    
    if( recordCount>0 && recordCount % 1000==0 ) {
        conn.commit();
    }
}

conn.commit();
logger.info("#"+index+" "+insertedActual+" records(expected:"+recordCount+") have been inserted to table:'"+tableName+"'.");

只是纯Insert语句插入提交,没想速度居然差不多。真应了那句话,纸上得来终觉浅,绝知此事要躬行。

参考资料:

1. https://www.cnblogs.com/myseries/p/11191134.html

2.https://www.cnblogs.com/shizhijie/p/7458813.html

--END-- 2019-10-10 8:15

原文地址:https://www.cnblogs.com/heyang78/p/11643169.html