JDBC批量插入性能

64 mysql performance jdbc batch-file

我需要在mysql数据库中插入几亿条记录.我一次批量插入100万.请参阅下面的代码.这看起来很慢.有没有办法优化它?

try {
        // Disable auto-commit
        connection.setAutoCommit(false);

        // Create a prepared statement
        String sql = "INSERT INTO mytable (xxx), VALUES(?)";
        PreparedStatement pstmt = connection.prepareStatement(sql);

        Object[] vals=set.toArray();
        for (int i=0; i<vals.length; i++) {
            pstmt.setString(1, vals[i].toString());
            pstmt.addBatch();
        }

        // Execute the batch
        int [] updateCounts = pstmt.executeBatch();
        System.out.append("inserted "+updateCounts.length);
Run Code Online (Sandbox Code Playgroud)

小智 164

我有一个与mysql类似的性能问题,并通过在连接url中设置useServerPrepStmtsrewriteBatchedStatements属性来解决它.

Connection c = DriverManager.getConnection("jdbc:mysql://host:3306/db?useServerPrepStmts=false&rewriteBatchedStatements=true", "username", "password");
Run Code Online (Sandbox Code Playgroud)

  • @Kimble - 为什么不接受这个答案呢?谢了哥们!这就像魔法一样! (4认同)
  • [驱动程序属性的MySQL参考文档](http://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html)已经移动. (3认同)
  • 10秒而不是1小时.当之无愧的+1! (2认同)
  • 你能解释为什么添加useServerPrepStmts = false有效吗?在阅读/sf/ask/2260056291/之后,我认为情况正好相反.我确定你是对的我只是不完全理解为什么/如何设置提高性能?谢谢. (2认同)

Era*_*ran 55

我想扩展Bertil的答案,因为我一直在试验连接URL参数.

rewriteBatchedStatements=true是重要的参数.useServerPrepStmts默认情况下已经为false,即使将其更改为true也不会对批量插入性能产生太大影响.

现在我认为是时候写一下如何rewriteBatchedStatements=true大幅提升性能.它由rewriting of prepared statements for INSERT into multi-value inserts when executeBatch()(来源)完成.这意味着n每次executeBatch()调用时都不会将以下INSERT语句发送到mysql服务器:

INSERT INTO X VALUES (A1,B1,C1)
INSERT INTO X VALUES (A2,B2,C2)
...
INSERT INTO X VALUES (An,Bn,Cn)
Run Code Online (Sandbox Code Playgroud)

它会发送一个INSERT语句:

INSERT INTO X VALUES (A1,B1,C1),(A2,B2,C2),...,(An,Bn,Cn)
Run Code Online (Sandbox Code Playgroud)

您可以通过切换mysql日志记录(by SET global general_log = 1)来观察它,这将记录发送到mysql服务器的每个语句的文件.


nos*_*nos 13

您可以插入多行与一个INSERT语句,一次做几千可以大大加快速度,那是不是做如形式的3个插入,INSERT INTO tbl_name (a,b,c) VALUES(1,2,3);你做INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(1,2,3),(1,2,3);(这可能是JDBC .addBatch()做类似的优化现在-尽管MySQL的addBatch使用才能完全未优化,只是发出单个查询无论如何-我不知道这是否仍与最新的驱动程序的情况下)

如果你真的需要的速度,用逗号分隔的文件加载数据LOAD DATA INFILE,我们避开7-8倍的加速这样做,这样做VS数以千万计的刀片.

  • 我不认为它可以过滤,但您可以自己清理数据,使用已清理的数据写入新文件并加载该文件. (3认同)

Wri*_*ken 5

如果:

  1. 这是一个新表,或者要插入的数量大于已插入的数据
  2. 桌子上有索引
  3. 插入期间,您不需要其他访问表的权限

然后ALTER TABLE tbl_name DISABLE KEYS可以大大提高插入的速度。完成后,请运行ALTER TABLE tbl_name ENABLE KEYS以开始建立索引,这可能需要一段时间,但所需时间不及每次插入操作的时间。