如何使使用QueryRunner更快地插入数据?

时间:2018-06-29 19:03:09

标签: java java-8 oracle12c apache-commons-dbcp

即使对于大量数据,使用QueryRunner读取数据也相对较快。
但是,当我插入数据时,它花费的时间更长。 (50条记录需要10到20秒的时间)

我基本上是在尝试从一个数据库中的一组表中读取记录到另一个数据库中。 我无法使用数据库链接,因为我没有创建一个到另一个数据库的权限。 我不能使用Oracle的COPY TO命令,因为某些字段是TIMESTAMPS,而COPY命令不支持该字段。 我不能使用PL / SQL,因为它必须是动态的。

我正在考虑使用SQL * Plus和SQL * Loader创建Shell或批处理脚本,但希望使用Java解决方案。

QueryRunner的替代方案也可以。只要他们可以相对快速地插入数据。

我的猜测是QueryRunner会按顺序分别请求每组值,而不是带有一堆输入值的单个请求。

使用:Java 1.8,commons-dbcp:1.4,commons-dbutils:1.7

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbutils.BasicRowProcessor;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.RowProcessor;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

    private final int colCount;
    private final int commitCount;

    private final String tableName;
    private final String insertSql;

    private final RowProcessor rowHandler = new BasicRowProcessor();
    private final QueryRunner devQueryRunner;

    @Override
    public Long handle(ResultSet rs) throws SQLException {
        long readCount = 0;
        long writeCount = 0;

        Object[][] params = new Object[commitCount][colCount];
        try (Connection conn = devQueryRunner.getDataSource().getConnection()) {
            int row = 0;
            while (rs.next()) {
                readCount++;
                params[row++] = rowHandler.toArray(rs);
                if (row >= commitCount) {
                    insertRunner.batch(conn, insertSql, params);
                    writeCount+=row;
                    row = 0;
                }
            }
            if (row > 0) {
                devQueryRunner.batch(conn, insertSql, Arrays.copyOf(params, row));
            }
            return readCount;
        } finally {
            if (logger.isInfoEnabled()) {
                logger.info(tableName+"[readCount="+readCount+", writeCount="+writeCount+"]");
            }
        }
    }

更新#1

使用PreparedStatement进行写入的时间(这太慢了):

  

读取50:0ms
  写50:1430ms
  读取50:0ms
  写50:1899毫秒
  读取50:0ms
  写50:805ms
  读取50:0ms
  写50:377ms
  读取50:0ms
  写50:1131毫秒
  读取50:0ms
  写50:859毫秒
  读取50:0ms
  写50:2131ms
  读取50:0ms
  写50:2355ms
  读取10000:0ms
  写10000:925584ms
  读取10000:0ms
  写10000:604083ms

0 个答案:

没有答案