如何在不构建字符串的情况下使用JDBC进行扩展插入?

时间:2009-07-02 08:07:44

标签: java sql mysql jdbc

我有一个解析日志文件并将大量数据插入数据库的应用程序。它是用Java编写的,并通过JDBC与MySQL数据库进行通信。我已经尝试了不同的方法来插入数据,以便找到最快的特定用例。目前看来表现最佳的一个是发布扩展插入(例如一个包含多行的插入),如下所示:

INSERT INTO the_table (col1, col2, ..., colN) VALUES
(v1, v2, v3, ..., vN),
(v1, v2, v3, ..., vN),
...,
(v1, v2, v3, ..., vN);

行数可以是数万。

我已经尝试过使用预处理语句,但它的速度远远不够快,可能是因为每个插入内容仍然分别发送到数据库,并且表需要锁定等等。我之前在我处理代码的同事尝试使用批处理,但这也表现不佳。

问题是使用扩展插入意味着我可以告诉我需要自己构建SQL字符串(因为行数是可变的),这意味着我打开了各种SQL注入向量没有足够的智慧去发现自己。必须有更好的方法来做到这一点。

显然我逃避了我插入的字符串,但只有str.replace("\"", "\\\"");(重复',?和\)之类的东西,但我确信这还不够。

5 个答案:

答案 0 :(得分:4)

预备语句+批量插入:

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();

答案 1 :(得分:1)

我会尝试对您的插页进行批处理,看看它是如何执行的。

阅读此内容(http://www.onjava.com/pub/a/onjava/excerpt/javaentnut_2/index3.html?page=2)以获取有关批处理的更多信息。

答案 2 :(得分:1)

如果您要加载数以万计的记录,那么最好使用批量加载器。

http://dev.mysql.com/doc/refman/5.0/en/load-data.html

答案 3 :(得分:1)

关于扩展插入和批处理单个插入之间的区别,我决定使用扩展插入的原因是因为我注意到我的代码花了很多时间从终端插入大量的行而不是mysql。这是即使我批量批量插入5000个。最终的解决方案是使用扩展插入。

我很快重新测试了这个理论。

我拿了一个有120万行的表的两个转储。一个使用mysqldump获得的默认扩展插入语句,另一个使用:

mysqldump --skip-extended-insert

然后我只是将文件再次导入新表并计时。

扩展插入测试在1分35秒内完成,另一个在3分49秒内完成。

答案 4 :(得分:0)

完整的答案是使用rewriteBatchedStatements=true配置选项 dfa's answer使用批处理语句。

相关的mysql documentation

有效的MySQL example