MySQL更新正在进行中

时间:2010-08-14 22:14:06

标签: java mysql performance

嘿,我试图将大约600000个令牌包含到我的MySQL数据库表中。我正在使用的引擎是InnoDB。更新过程将永远持续下去:(。所以我最好的猜测是我在代码中完全遗漏了一些东西,而我正在做的事情只是简单的愚蠢。

也许有人对我的表现有什么看法有自发的想法:

这是我的代码:

public void writeTokens(Collection<Token> tokens){

    try{
        PreparedStatement updateToken = dbConnection.prepareStatement("UPDATE tokens SET `idTag`=?, `Value`=?, `Count`=?, `Frequency`=? WHERE `idToken`=?;");

        for (Token token : tokens) {

            updateToken.setInt(1, 0);
            updateToken.setString(2, token.getWord());
            updateToken.setInt(3, token.getCount());
            updateToken.setInt(4, token.getFrequency());
            updateToken.setInt(5, token.getNounID());

            updateToken.executeUpdate();
        }
    }catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

非常感谢!

3 个答案:

答案 0 :(得分:5)

我没有针对您的Java特定答案,而是将整个shebang包装在一个事务中。如果不这样做,则MySQL(在针对InnoDB写入时)启动并为每个更新语句提交一个新事务。

在开始调用之前执行START TRANSACTION,并在完成所有更新/插入后执行COMMIT。我还认为MySQL推迟了索引更新,直到事务结束,如果你要更新索引字段,这应该有助于提高性能。

答案 1 :(得分:4)

如果您的表中的一个或多个字段有索引,则每个更新都会强制重建这些索引,这可能需要一段时间才能接近数十万个条目。

PreparedStatement附带了一个addBatch()方法 - 我没有使用它,但是如果我正确使用它,你可以将几批记录传输到你准备好的语句,然后一次更新。这将索引重建的数量从600.000减少到1 - 您应该感觉不同:)

答案 2 :(得分:3)

每个更新语句都需要往返数据库。这会给你带来巨大的性能影响。

有几种方法可以将此数据插入数据库,而无需执行数十万次查询:

  • 使用批量插入(LOAD DATA INFILE)。
  • 使用一次插入多行的insert语句。例如,您可以为每个插入语句插入100行。

然后,您可以使用单个update语句将数据复制到目标表中。这将减少服务器往返次数,从而提高性能。