MySQL更新需要很长时间

5

嘿,我正在尝试将约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个回答

5
我没有针对Java的具体答案,但是请将整个操作放在一个事务中。如果不这样做,在写入InnoDB时,MySQL会为每个更新语句启动并提交一个新的事务。
只需在开始调用之前执行START TRANSACTION,并在完成所有更新/插入后执行COMMIT。我还认为,MySQL还推迟索引更新直到事务结束,这也应该有助于显着提高性能,特别是在更新索引字段时。

为此,从数据库角度来看,应该具有相同的效果。 - Nicolas78
这些都是很好的答案...可惜我只能接受一个作为我的采纳答案,因为真正起作用的是所有答案的组合。再次感谢@All。 - evermean

4
如果您的表中有一个或多个字段的索引,则每次更新都会强制重建这些索引,随着条目数量接近几十万条,这可能需要一段时间。
PreparedStatement带有一个addBatch()方法 - 我没有使用过它,但如果我理解正确,您可以将多个记录批量传输到预处理语句中,然后一次性更新。这将把索引重建的次数从600,000降至1 - 您应该能够感受到差异 :)

3
每个更新语句都需要与数据库进行一次往返。这会给您带来巨大的性能损失。
有几种方法可以将此数据插入到数据库中,而不执行数十万个查询:
  • 使用批量插入(LOAD DATA INFILE)。
  • 使用单个插入语句一次插入多行。例如,您可以每个插入语句插入100行。
然后,您可以使用单个更新语句将数据复制到目标表中。这将减少服务器往返次数,提高性能。

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