Мне все равно, насколько мощным является язык программирования, если его синтаксис не интуитивен, и я не могу отложить его на некоторое время и вернуться к нему без особых усилий, чтобы обновить детали. Я бы предпочел, чтобы сам язык был интуитивно понятным, чем загадочным, но мощным для создания DSL. Компьютерный язык - это пользовательский интерфейс для ME, и я хочу, чтобы он был разработан для интуитивно понятной простоты использования, как и любой другой пользовательский интерфейс.
Советы по быстрой вставке:
Используйте этот синтаксис вставки:
вставить в таблицу (col1, col2) значения (val1, val2), (val3, val4), ...
Удалить все ключи / индексы перед вставкой.
Вы ОБЯЗАТЕЛЬНО отключили автоматические фиксации в драйвере JDBC?
Это типичный убийца производительности для клиентов JDBC.
Я бы, вероятно, выбрал большое количество, например, 10 тыс. Строк, и загрузил такое количество строк из CSV, обработал данные и выполнил пакетное обновление, а затем повторил бы, пока вы не пройдете через весь csv. В зависимости от обработки / количества данных 1,8 млн строк не должны занимать 10 часов, скорее 1-2 часа, в зависимости от вашего оборудования.
edit: упс, упущена довольно важная часть, у вашего мошенника должна быть установлена автоматическая фиксация значение false, код, из которого я скопировал это, делал это как часть метода GetConnection ().
Connection con = GetConnection();
con.setAutoCommit(false);
try{
PreparedStatement ps = con.prepareStatement("INSERT INTO table(col1, col2) VALUES(?, ?)");
try{
for(Data d : massagedData){
ps.setString(1, d.whatever());
ps.setString(2, d.whatever2());
ps.addBatch();
}
ps.executeBatch();
}finally{
ps.close();
}
}finally{
con.close();
}
Вам действительно следует использовать для этого LOAD DATA в самой консоли MySQL, а не работать через код ...
LOAD DATA INFILE 'data.txt' INTO TABLE db2.my_table;
Если вам нужно манипулировать данными, я все равно рекомендую манипулировать в памяти , переписывая его в плоский файл и отправляя его в базу данных с помощью LOAD DATA, я думаю, это должно быть более эффективным.
В зависимости от того, что именно вам нужно сделать с данными перед их вставкой, ваши лучшие варианты с точки зрения скорости:
Другая идея: используете ли вы PreparedStatement для вставки данных с помощью JDBC?
Самая большая проблема с производительностью, скорее всего, связана не с java, а с mysql, в частности с любыми индексами, ограничениями и внешними ключами в таблице, в которую вы вставляете. Прежде чем приступить к вставкам, убедитесь, что вы их отключили. Повторное включение их в конце займет значительное время, но это намного эффективнее, чем оценка их базой данных после каждого оператора.
Вы также можете столкнуться с проблемами производительности mysql из-за размера вашей транзакции. Ваш журнал транзакций станет очень большим с таким количеством вставок, поэтому выполнение фиксации после X вставок (скажем, 10 000–100 000) также поможет ускорить вставку.
На уровне jdbc убедитесь, что вы используете addBatch ( ) и executeBatch () в вашем PreparedStatement, а не в обычном executeUpdate ().
Разве не было бы быстрее, если бы вы использовали LOAD DATA INFILE вместо вставки каждой строки?
Если вы еще не сделали этого, попробуйте использовать тип таблицы MyISAM, только прежде чем это сделать, обязательно прочтите о его недостатках. Как правило, это быстрее, чем другие типы таблиц.
Если ваша таблица имеет индексы, обычно быстрее их отбросить, а затем добавить обратно после импорта.
Если ваши данные представляют собой все строки, но лучше подходят как в реляционной базе данных лучше вставлять целые числа, указывающие на другие значения, чем хранить длинную строку.
Но в целом,
Я бы запустил три потока ...
1) Читает входной файл и помещает каждую строку в очередь преобразования 2) Извлекает из очереди, преобразует данные и помещает в очередь БД 3) Извлекает из очереди db и вставляет данные
Таким образом, вы можете читать данные с диска, пока потоки db ждут завершения своего ввода-вывода, и наоборот
Это интересное чтение: http://dev.mysql.com/doc/refman/5.1/en/insert-speed.html
Вы можете улучшить производительность групповой INSERT из MySQL / Java, используя возможность пакетной обработки в его JDBC-драйвере Connector J.
MySQL «неправильно» обрабатывает пакеты (см. Ссылку на мою статью внизу), но он может переписывать INSERT, чтобы использовать необычный синтаксис MySQL, например вы можете указать драйверу переписать два INSERT:
INSERT INTO (val1, val2) VALUES ('val1', 'val2');
INSERT INTO (val1, val2) VALUES ('val3', 'val4');
как один оператор:
INSERT INTO (val1, val2) VALUES ('val1', 'val2'), ('val3','val4');
(Обратите внимание, что я не говорю , что вам нужно переписать свой SQL таким образом; драйвер делает это, когда может)
Мы сделали это для собственного исследования объемных вставок: разница была на порядок. Используется с явными транзакциями, как упоминалось другими, и в целом вы увидите большое улучшение.
Соответствующее значение свойства драйвера:
jdbc:mysql:///<dbname>?rewriteBatchedStatements=true
См .: Десятикратное увеличение производительности для пакетных вставок с MySQL Connector / J уже в пути