Java批量插入MySQL非常缓慢。

3
我是一名有用的助手,可以为您翻译文本。

可能是重复问题:
JDBC批量插入性能

我在一个类中有以下方法:

    public void insertShingleSets(Vector<ShingleSet> shingleSets)
    {
        String sql = "INSERT   INTO tblPostingsShingles("+
                "rowId, " +                    
                "shingle) " +                     
                "VALUES(?,?);";

        PreparedStatement statement = null;
        try {
            statement = conn.prepareStatement(sql);
            for (int i = 0; i < shingleSets.size(); i++)
            {   String id = shingleSets.get(i).getRowId();
                String shingle = shingleSets.get(i).getShingle();
                statement.setInt(1, Integer.parseInt(id));
                statement.setString(2, shingle);
                statement.addBatch();
                if ((i + 1) % 1000 == 0) {
                    System.out.println("doing a batch " + i);         //-------------
                    statement.executeBatch(); // Execute every 1000 items.
                    System.out.println("done batch " + i);            //-------------
                             }
            }
            statement.executeBatch();
        }
       catch (SQLException ex)
            {
                // handle any errors
                System.out.println("SQLException: " + ex.getMessage());
                System.out.println("SQLState: " + ex.getSQLState());
                System.out.println("VendorError: " + ex.getErrorCode());
            }

        finally {
            if (statement != null)
                try { statement.close();
                } catch (SQLException logOrIgnore) {}
            if (conn != null)
                try { conn.close();
                } catch (SQLException logOrIgnore) {}
        }
    }

执行 System.out.println("doing a batch " + i); 和执行 System.out.println("done batch " + i); 之间的时间大约为30秒,考虑到只向三列表中插入了两列(另一列是自动编号主键,在开始/测试时表中没有行),这似乎有点多余。我唯一能想到的是在调用此方法之前,另一个方法使用查询来检查 tblPostingsShingles 表中是否存在某些 rowIds。然而,我认为当该方法完成时任何锁定都会被释放(它与此方法具有相同的 finally 子句)。任何建议将不胜感激。 戴夫

如果你在每个方法中关闭连接,那么谁会重新打开它呢? - Jan Thomä
2个回答

1
你可以尝试不同的批处理大小,但我曾经使用500个批次的进程速度相当快,而1000个批次并不算太大——我看不出为什么会花费那么长时间——这明显慢了一个数量级。
其他可能的性能瓶颈是你的mysql配置和网络连接速度。这种速度比一次写入一个更快吗?

我对mysql有点陌生。但是它安装在同一台计算机上(即本地服务器)。我原以为mysql.slow_log中会出现一些内容,但是它是空的。我没有故意更改任何配置,但是有没有办法可以检查这些配置?它似乎非常慢。我认为由于本地服务器,网络连接不适用于此吗?我计时了插入一行所需的时间,并将其计算为70702840纳秒,即0.07秒。这不是很多吗?谢谢任何建议。 - user725687
在你的本地电脑上,这似乎非常慢,除非你的本地电脑是一台约1990年的IBM PC-Junior。我不认为慢查询日志会显示插入操作,尽管我不能保证。在批处理之前尝试关闭驱动程序中的自动提交,并手动触发提交。 - Steve B.

0
我建议您尝试使用更小的批处理大小。通常情况下,在进行批量插入时,我将批处理大小限制在每次20-50行。现在,使用1000行批处理,您的作业很可能会被阻止在数据库和网络I/O上。如果您减小批处理大小,可能可以加快进程速度。

缩小批处理的大小可以提高批处理的处理时间,但它会如何影响整体处理时间? - Dmitriy R
当然,我已经将它从1000行减少到了200行,但是它所需的时间仍然是五分之一左右 - 也就是说,处理200行仍需要大约8-10秒钟。 - user725687
是的,那很糟糕。我找到了这个网址:http://dev.mysql.com/doc/refman/5.0/en/insert-speed.html,你可能需要查看关于 LOCK TABLES 的部分,你可以试试吗? - jonathan.cone
谢谢Jonathan。我想可能是我的电脑或其他原因 - 现在换了另一台电脑,看起来没问题了。 - user725687

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接