Пакетная вставка в mysql с java - PullRequest
0 голосов
/ 29 апреля 2020

Мне известен этот вопрос , но ответы не соответствуют тому, что я ищу (объяснено в конце).

Я хотел бы вставить несколько строк в порядка десятков или сотен тысяч, до MySQL версии базы данных 5.6 с Java.

Это будет выполняться неоднократно внутри тестов, поэтому я хотел бы сократить время, которое требуется.

В прошлом я делал подобные вещи с Node.js и Postgres и использовал два подхода:

.1 Использование jsonb_to_recordset

INSERT INTO some_table (a, b) SELECT x.a, x.b FROM json_to_recordset('[{"a":1,"b":"foo"},{"a":"2","c":"bar"}]') AS x(a int, b text);

Массив будет передать в качестве параметра, и будет только один запрос вставки с таким количеством строк, как массив. Этот подход значительно быстрее, чем делать n вставок. И может управлять любым массивом, который легко помещается в памяти. Кроме того, запрос будет легко читать и сохранять c.

.2 Загрузка из потока узлов непосредственно в базу данных

pool.connect(function(err, client, done) {
  var stream = client.query(copyFrom('COPY my_table FROM STDIN'));
  var fileStream = fs.createReadStream('some_file.tsv')
  fileStream.on('error', done);
  stream.on('error', done);
  stream.on('end', done);
  fileStream.pipe(stream);
});

Этот параметр имеет очень низкий объем занимаемой памяти, и он может адаптироваться к потоку из файла или динамически генерируемого потока.

Возможно ли применить какой-либо из подходов в Java?

Вариант 1. Я предполагаю, что это невозможно в v 5.6, поскольку он не поддерживает JSON, но, возможно, в более новых версиях.

Вариант 2. mysql допускает загрузку файл с stdin вместо диска, поэтому потенциально hibernate может отправить поток java на mysql без загрузки всего в памяти.

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

Принятый ответ:

INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9);

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

Второе решение:

connection con.setAutoCommit(false); 
PreparedStatement prepStmt = con.prepareStatement("UPDATE DEPT SET MGRNO=? WHERE DEPTNO=?");
prepStmt.setString(1,mgrnum1);                 
prepStmt.setString(2,deptnum1);
prepStmt.addBatch();

prepStmt.setString(1,mgrnum2);                        
prepStmt.setString(2,deptnum2);
prepStmt.addBatch();

int [] numUpdates=prepStmt.executeBatch();

Также потребует пакетирование в пакете, если слишком много записей, чтобы избежать проблемы с памятью.

Четвертое решение: вставка из файла. Имеет проблему, что требуется доступ к диску базы данных. .2 предложенное здесь было бы улучшенным решением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...