Вставьте тысячи записей из Java в Oracle, как мне добиться максимальной производительности? - PullRequest
0 голосов
/ 09 ноября 2019

Мне нужно сделать пакетный процесс в java, который будет читать файл с переменным количеством записей (хотя можно с уверенностью принять 5k +), обрабатывать их и затем вставлять записи в базу данных oracle 11g. Мне нужно сделать это через вызов (ы) хранимой процедуры.

Я уже несколько месяцев назад совершал аналогичный процесс, которым я не очень горжусь (без особой причины, кроме как я уверен,это совсем не оптимально). В предыдущем решении я сохранил все в памяти и для вставки строк я создал инструкцию INSERT ALL, в которой я только что добавил все записи с помощью строителя строк, и просто выполнил эту одну инструкцию, чтобы вставить 15k + записей за один раз. На этот раз мне нужно использовать хранимую процедуру для вставки данных. Я читал и теперь знаю, что существуют способы отправки массивов данных в хранимые процедуры, поэтому я мог бы отправлять несколько записей одновременно.

Должен ли я создать хранимую процедуру, которая получает массивы, и просто отправлять все - потенциально тысячи - записей за один вызов этого SP? Или я должен ограничить его определенным количеством записей за раз и вызывать это количество SP (записей / лимитов) раз?

Или я должен избегать использования массивов и иметь хранимую процедуру, которая только получаетинформация для одной записи, и вызывать ее столько раз, сколько у меня есть записей?

Если бы мне нужно было сделать несколько вызовов, я подумал об использовании PreparedStatements и методов .addBatch () и .executeBatch (),это будет путь?

Мне нужно иметь возможность вставить все записи и откат в случае любой ошибки. Для которых я собираюсь использовать транзакции. Технически я не обязан соблюдать какие-либо ограничения в плане производительности, но я заинтересован в этой теме, и сейчас самое время начать беспокоиться об этом, поэтому я хотел бы получить советы и подсказки от кого-то, имеющего опыт в этой теме. .

Ответы [ 2 ]

1 голос
/ 09 ноября 2019

"Должен ли я создать хранимую процедуру, которая получает массивы, и просто отправлять все - потенциально тысячи - записей за один вызов этого SP? Или я должен ограничить ее определенным количеством записей ввремя и назвать это SP (записей / лимит) количество раз? "

Ограничение на определенное количество записей. Я обычно начинаю со 100 до 1000, в зависимости от общего размера записи.

"Или я должен избегать использования массивов и иметь хранимую процедуру, которая просто получает информациюза одну запись, и назвать ее столько раз, сколько у меня есть записей? "

Нет. Вы будете тратить впустую ЦП и, прежде всего, время: каждый раз, когда Java вызывает базу данных, уходит время только на отправку сообщения и получение ответа (связано с «задержкой»).

"Если бы мне приходилось делать несколько вызовов, я думал об использовании PreparedStatements и методов .addBatch () и .executeBatch (), это был бы путь? "

Да,но эти методы лучше всего подходят для операторов SQL (таких как INSERT), а не для вызовов хранимых процедур.

Мне нужно иметь возможность вставлять все записи и выполнять откат в случаелюбая ошибка.

Отключите автоматическую фиксацию (что я рекомендую в целом) и подтвердите, когда все в порядке.

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

В каждом случае жизненно важно использовать связывать переменные , а не объединятьзначения в операторах SQL (или вызовы SP) в виде литералов.

С уважением, Stew Ashton

PS для записей 5k +, многопоточность избыточна.

0 голосов
/ 09 ноября 2019

Если вы используете хранимую процедуру (SP)?

Я не думаю, что это приведет к значительному улучшению производительности, поскольку у вас есть оператор INSERT. SP был бы полезен, если бы у вас были сложные запросы, и его использование сэкономило бы время компиляции запроса. Простая инструкция вставки не займет много времени для компиляции.

Так что, на мой взгляд, отправляйте ваш запрос на лету, используя Java PreparedStatement.

Подход, которому я следовал бы:

Поскольку вам необходимо вставить все данные и выполнить откат в случае ошибок, я бы посоветовал вам вставить весь набор данных в пакетах. В случае сбоя пакета вы можете просто откатить изменения для пакета и повторить вставку для пакета.

Если вы отправите весь набор данных за один снимок, вам придется откатить все изменение, вызванное ошибкой в ​​одном операторе вставки.

Еще одно преимущество использованияbatch - это то, что вы отправите данные пакета в одном соединении JDBC. Создание, поддержание и очистка соединения создает накладные расходы. Таким образом, пакетная обработка в некоторой степени экономит эти накладные расходы.

Кроме того, вы можете использовать многопоточность, где у вас могут быть задачи читать пакет данных, обрабатывать их и вставлять их (используя пакет). Ваши задачи могут получить доступ к соединениям JDBC из пула соединений, такого как HikariCP. Таким образом, хотя некоторые потоки заняты вставкой данных, другие могут читать и обрабатывать данные.

Некоторые материалы для чтения на многопоточных вставках: https://dba.stackexchange.com/questions/16131/how-does-oracle-handle-multiple-concurrent-inserts-against-one-table

PS: конструктивная критикаДобро пожаловать.

...