Как ускорить вставку данных с помощью QueryRunner? - PullRequest
0 голосов
/ 29 июня 2018

Считывание данных с помощью QueryRunner выполняется относительно быстро даже для больших объемов данных.
Однако, когда я иду, чтобы вставить данные, это занимает гораздо больше времени. (50 записей занимает 10-20 секунд)

Я в основном пытаюсь прочитать записи из набора таблиц в одной базе данных в другую. Я не могу использовать DB Links, потому что у меня нет прав на создание одной базы данных для другой. Я не могу использовать команды Oracle COPY TO, потому что некоторые поля являются TIMESTAMPS, которые не поддерживаются командой COPY. Я не могу использовать PL / SQL, потому что он должен быть динамическим.

Я рассматриваю возможность создания сценария оболочки или пакетного сценария с использованием SQL * Plus и SQL * Loader, но предпочел бы решение 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: 0мс
Напишите 50: 1430мс
Чтение 50: 0 мс
Напишите 50: 1899мс
Чтение 50: 0 мс
Напишите 50: 805мс
Чтение 50: 0 мс
Напишите 50: 377мс
Чтение 50: 0 мс
Напишите 50: 1131мс
Чтение 50: 0 мс
Напишите 50: 859мс
Чтение 50: 0 мс
Напишите 50: 2131мс
Чтение 50: 0 мс
Напишите 50: 2355мс
Чтение 10000: 0 мс
Напишите 10000: 925584мс
Чтение 10000: 0 мс
Напишите 10000: 604083мс

...