Я отвечу на ваши вопросы по очереди.
- Будет ли метод executeBatch попытаться отправить все данные сразу?
Это может варьироваться в зависимости от каждого драйвера JDBC, но те немногие, которые я изучал, будут перебирать каждую запись пакета и каждый раз отправлять аргументы вместе с подготовленным дескриптором оператора в базу данных для выполнения. То есть в приведенном выше примере было бы 50 000 выполнений подготовленного оператора с 50 000 пар аргументов, но эти 50 000 шагов можно выполнить в «внутреннем цикле» более низкого уровня, в котором и происходит экономия времени. довольно растянутая аналогия, это все равно что выйти из «пользовательского режима» в «режим ядра» и запустить там весь цикл выполнения. Вы экономите затраты на погружение и выход из этого низкоуровневого режима для каждой записи партии.
- Есть ли способ определения размера партии
Вы определили это здесь неявно, вставив 50 000 наборов аргументов перед выполнением пакета с помощью Statement#executeBatch()
. Размер партии один так же действителен.
- Есть ли лучший способ ускорить процесс массовой вставки?
Подумайте об открытии транзакции перед пакетной вставкой и подтвердите ее позже. Не позволяйте ни базе данных, ни драйверу JDBC накладывать границу транзакции вокруг каждого шага вставки в пакет. Вы можете управлять слоем JDBC с помощью метода Connection#setAutoCommit(boolean)
. Сначала выведите соединение из режима автоматической фиксации , затем заполните свои пакеты, запустите транзакцию, выполните пакет, а затем подтвердите транзакцию с помощью Connection#commit()
.
В этом совете предполагается, что ваши вставки не будут конкурировать с параллельными авторами, и предполагается, что эти границы транзакций дадут вам достаточно согласованные значения, считанные из исходных таблиц для использования во вставках. Если это не так, отдайте предпочтение скорости, а не скорости.
- Лучше ли использовать обновляемый
ResultSet
или PreparedStatement
с пакетным выполнением?
Ничто не сравнится с тестированием с выбранным вами драйвером JDBC, но я ожидаю, что последние - PreparedStatement
и Statement#executeBatch()
выиграют здесь. Дескриптор оператора может иметь связанный список или массив «пакетных аргументов», причем каждая запись является набором аргументов, предоставляемых между вызовами Statement#executeBatch()
и Statement#addBatch()
(или Statement#clearBatch()
). Список будет расти с каждым вызовом addBatch()
и не будет сбрасываться до тех пор, пока вы не наберете executeBatch()
. Следовательно, экземпляр Statement
действительно действует как буфер аргументов; вы торгуете памятью для удобства (используя экземпляр Statement
вместо вашего собственного внешнего буфера набора аргументов).
Опять же, вы должны считать эти ответы общими и умозрительными, если мы не обсуждаем специфический драйвер JDBC. Каждый драйвер отличается по сложности, и каждый будет отличаться в том, какие оптимизации он преследует.