Производительность Oracle и JDBC: INSERT ALL vs prepareStatement.addBatch

У меня есть приложение java с базой данных базы данных Oracle, в которое мне нужно вставить несколько строк. Я видел дискуссию о вставке нескольких строк в Oracle, но меня также интересует, как влияет производительность на JDBC в броске в миксе.

Я вижу несколько возможностей:

Вариант 1: Используйте однострочную вставку PreparedStatement и выполните ее несколько раз:

String insert = "Insert into foo(bar, baz) values (?, ?)";
PreparedStatement stmt = conn.prepareStatement(insert);
for(MyObject obj : someList) {
    stmt.setString(1, obj.getBar());
    stmt.setString(2, obj.getBaz());
    stmt.execute();
}

Вариант 2: Создайте инструкцию Oracle INSERT ALL:

String insert = "INSERT ALL " +
    "INTO foo(bar, baz), (?, ?) " +
    "INTO foo(bar, baz), (?, ?) " +
    "SELECT * FROM DUAL";
PreparedStatement stmt = conn.prepareStatement(insert);
int i=1;
for(MyObject obj : someList) {
    stmt.setString(i++, obj.getBar());
    stmt.setString(i++, obj.getBaz());
}
stmt.execute();

Вариант 3: Используйте функцию addBatch для PreparedStatement:

String insert = "Insert into foo(bar, baz) values (?, ?)";
PreparedStatement stmt = conn.prepareStatement(insert);
for(MyObject obj : someList) {
    stmt.setString(1, obj.getBar());
    stmt.setString(2, obj.getBaz());
    stmt.addBatch();
}
stmt.execute();

Я предполагаю, что еще одна возможность - создать CSV файл и использовать SQL Loader, но я не уверен, что это будет действительно быстрее, если вы добавите дополнительные накладные расходы на создание файла CSV...

Итак, какой вариант выполнил бы самый быстрый?

Ответ 1

Используйте функцию addBatch для PreparedStatement для чего-либо, расположенного ниже 1 000 000 строк.

Каждый дополнительный компонент, добавляемый в ваш код, увеличивает зависимости и точки отказа. Если вы спуститесь по этому маршруту (внешние таблицы, загрузчик sql и т.д.), Убедитесь, что это действительно стоит.

Сериализация данных в файл csv, перемещение его в место, читаемое базой данных, будет легко занимать секунду или около того. За это время я мог бы вставить 20 000 строк, если бы я просто втянул его и начал вставлять с помощью JDBC.

Ответ 2

SQL Loader выглядит лучше, даже без прямой загрузки, но его трудно поддерживать. Пакетная вставка в 2-4 раза быстрее, чем отдельные инструкции вставки. Вставьте все так же, как вставка пакета, и оба они будут быстрее, чем реализация PL/SQL.

Также вы можете прочитать this тему AskTom.

Ответ 3

Использование партии может быть прозрачным для программиста. Вот цитата из здесь:

Установка значения пакетного подключения

Вы можете указать значение пакета по умолчанию для любого подготовленного Oracle оператора в вашем соединении Oracle. > Для этого используйте метод setDefaultExecuteBatch() объекта OracleConnection. Например, следующий код устанавливает значение по умолчанию по умолчанию для 20 для всех подготовленных объектов-операторов, связанных с объектом соединения:

((OracleConnection) сопп).setDefaultExecuteBatch(20);

Несмотря на то, что это устанавливает значение пакета по умолчанию для всех подготовленных операторов соединения, вы можете переопределить его, вызвав setDefaultBatch() в отдельных подготовленных оператором Oracle.

Значение пакета соединения будет применяться к объектам оператора, созданным после того, как было установлено это пакетное значение.