我有一个分析日志文件并将大量数据插入数据库的应用程序。它是用Java编写的,并通过JDBC与MySQL数据库进行通信。我尝试了不同的方法来插入数据,以针对我的特定用例找到最快的方法。目前看来效果最好的一种是发出扩展插入(例如,一个具有多行的插入),如下所示:
INSERT INTO the_table (col1, col2, ..., colN) VALUES
(v1, v2, v3, ..., vN),
(v1, v2, v3, ..., vN),
...,
(v1, v2, v3, ..., vN);
行数可以是数万。
我已经尝试过使用准备好的语句,但是它的速度还差得很远,可能是因为每个插入仍然仍单独发送到DB,并且表需要锁定等等。在我尝试使用批处理功能之前,我曾在代码上工作的同事,但是这样做也不够好。
问题是,使用扩展插入意味着,据我所知,我需要自己构建SQL字符串(因为行数是可变的),这意味着我打开了各种SQL注入向量,在没有足够的智慧找到自己的地方。必须有一种更好的方法来做到这一点。
[显然,我对插入的字符串进行了转义,但仅使用类似str.replace("\"", "\\\"");
的字符串(对于',?和\重复),但是我确定这还不够。
准备好的语句+批处理插入:
PreparedStatement stmt = con.prepareStatement(
"INSERT INTO employees VALUES (?, ?)");
stmt.setInt(1, 101);
stmt.setString(2, "Paolo Rossi");
stmt.addBatch();
stmt.setInt(1, 102);
stmt.setString(2, "Franco Bianchi");
stmt.addBatch();
// as many as you want
stmt.executeBatch();
我将尝试批处理您的插入内容,并查看其效果。
已阅读此(http://www.onjava.com/pub/a/onjava/excerpt/javaentnut_2/index3.html?page=2)以获取有关批处理的更多信息。
如果要加载成千上万条记录,那么最好使用批量加载器。
关于扩展插入和批处理单个插入之间的区别,我决定使用扩展插入的原因是因为我注意到,从终端插入很多行比mysql花费了更多的时间。即使我要以5000个为批处理批量插入。最后的解决方案是使用扩展插入。
我很快就重新检验了这个理论。
我从一个具有120万行的表中转储了两个。一个使用默认的扩展插入语句,该语句是通过mysqldump获得的,另一个使用:
mysqldump --skip-extended-insert
然后我只是将文件再次导入到新表中并对其计时。
[扩展插入测试在1m35s内完成,另一个在3m49s中完成。
完整的答案是将rewriteBatchedStatements=true
配置选项以及