JDBC批量插入性能JDBC批量插入性能(JDBC batch insert performance

2019-05-10 12:32发布

我需要插入一对夫妇数亿记录到MySQL数据库。 在同一时间,我批其插入1个亿。 请在下面看我的代码。 这似乎是缓慢的。 有什么办法优化它?

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

Answer 1:

我也有类似的性能问题与MySQL和通过在连接URL设置useServerPrepStmtsrewriteBatchedStatements性能解决它。

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


Answer 2:

我想在贝蒂尔的回答扩大,因为我一直在尝试进行连接的URL参数试验。

rewriteBatchedStatements=true是重要的参数。 useServerPrepStmts已经是虚假的默认情况下,甚至将其更改为真不作在批量插入性能方面太大的差别。

现在我觉得是写的时候怎么rewriteBatchedStatements=true提高性能那么厉害。 它通过这样做rewriting of prepared statements for INSERT into multi-value inserts when executeBatch() 源 )。 这意味着不是发送以下n INSERT语句MySQL服务器每次executeBatch()被调用:

INSERT INTO X VALUES (A1,B1,C1)
INSERT INTO X VALUES (A2,B2,C2)
...
INSERT INTO X VALUES (An,Bn,Cn)

这将发出一个单一的INSERT语句:

INSERT INTO X VALUES (A1,B1,C1),(A2,B2,C2),...,(An,Bn,Cn)

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



Answer 3:

你可以用一个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数以千万计的刀片。



Answer 4:

如果:

  1. 这是一个新的表,或要插入的量大则已经插入数据
  2. 有此表的索引
  3. 你不需要在插入过程中的其他访问表

然后ALTER TABLE tbl_name DISABLE KEYS可以大大提高你插入的速度。 当你完成后,运行ALTER TABLE tbl_name ENABLE KEYS开始建立索引,这可能需要一段时间,但几乎没有,只要做它的每一次插入。



Answer 5:

您可以尝试使用DDBulkLoad对象。

// Get a DDBulkLoad object
DDBulkLoad bulkLoad = DDBulkLoadFactory.getInstance(connection);
bulkLoad.setTableName(“mytable”);
bulkLoad.load(“data.csv”);


Answer 6:

try {
        // Disable auto-commit
        connection.setAutoCommit(false);
        int maxInsertBatch = 10000;     
        // Create a prepared statement
        String sql = "INSERT INTO mytable (xxx), VALUES(?)";
        PreparedStatement pstmt = connection.prepareStatement(sql);

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

        // Execute the batch
        pstmt.executeBatch();
        System.out.append("inserted "+count);


文章来源: JDBC batch insert performance