我在一个简单的java控制台应用程序中使用PreparedStatement
来从InputStream
加载大量数据。
这是代码:
public void readStopTimes(CSVReader reader) throws IOException, SQLException {
String insertSql = "INSERT INTO stop_times VALUES (null, ?, ?, ?, ?, ?)";
PreparedStatement statement = db.prepareStatement(insertSql);
String [] nextLine;
long i = 0;
Chronometer chronometer = new Chronometer();
while ((nextLine = reader.readNext()) != null) {
if(i++ != 0) {
statement.setString(1, nextLine[0]);
if(nextLine[1].isEmpty())
statement.setNull(2, Types.TIME);
else
statement.setTime(2, Time.valueOf(nextLine[1]));
if(nextLine[2].isEmpty())
statement.setNull(3, Types.TIME);
else
statement.setTime(3, Time.valueOf(nextLine[2]));
statement.setString(4, nextLine[3]);
statement.setInt(5, Integer.parseInt(nextLine[4]));
statement.addBatch();
}
if(i++ % 1000 == 0) {
statement.executeBatch();
}
if(chronometer.count() > 5000) {
chronometer.restart();
log.debug("Analyzed {} rows", i);
}
}
statement.executeBatch();
db.commit();
}
每1000次插入我正在执行批处理,每5秒我打印一次日志。
从日志中可以看出,该算法在开始时运行速度非常快,在前25秒内计算总计超过400万行,然后减慢速度,在5秒内只添加2行批次。
我需要插入超过500万行,你有更快的替代方案吗?
答案 0 :(得分:1)
innodb_flush_log_at_trx_commit = 2
或者如果你能确保你的mysql没有崩溃而不是innodb_flush_log_at_trx_commit = 0
sync_binlog = 0
您可以尝试通过Load data infile . . . . .
命令直接将CSV文件放到MySql中,这非常快。
答案 1 :(得分:0)
尝试在statement.executeBatch()之后进行调用;而不仅仅是在最后。这应该允许在你继续时刷新插入,因为mysql在你的插入上留下了标签,所以它可以在必要时将它们全部回滚。
答案 2 :(得分:0)
尝试多批次而不是单批次添加数据。每批后提交并跟踪已处理的数据。或者您可以使用临时表将数据添加到表中,一旦完成,重命名表,以防出现故障,重新启动或从保存点开始。