更新单个表的多行

Moh*_*dil 5 java mysql

我需要更新具有超过60k行的表的每一行.目前我这样做 -

public void updateRank(Map<Integer,Double> map){
        Iterator<Entry<Integer, Double>> it = map.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<Integer,Double> pairs = (Map.Entry<Integer,Double>)it.next();
            String query = "update profile set rank = "+ pairs.getValue()+ " where profileId = "+pairs.getKey();
            DBUtil.update(query);
            it.remove();
        }       
}
Run Code Online (Sandbox Code Playgroud)

仅此方法需要大约20分钟才能完成,每行(60k)命中数据库就是我认为的原因.(虽然我使用dbcp进行连接池,最多有50个活动连接)

如果我能够使用单个数据库命中更新行,那就太好了.那可能吗 ?怎么样 ?

或者其他任何改善时间的方法?

Ste*_*ler 11

如果每一行都应该获得不能从数据库中的现有数据派生的不同值,那么您可以做很多事情来优化整体复杂性.所以不要指望太多的奇迹.

也就是说,您应该开始使用预准备语句和批处理:

public void updateRank(Map<Integer,Double> map){
    Iterator<Entry<Integer, Double>> it = map.entrySet().iterator();
    String query = "";
    int i = 0;

    Connection connection = getConnection(); // get the DB connection from somewhere
    PreparedStatement stmt = connection.prepareStatement("update profile set rank = ? where profileId = ?");

    while (it.hasNext()) {
        Map.Entry<Integer,Double> pairs = (Map.Entry<Integer,Double>)it.next();
        stmt.setInt(1, pairs.getValue());
        stmt.setDouble(2, pairs.getKey());
        stmt.addBatch(); // this will just collect the data values
        it.remove();
    }       
    stmt.executeBatch(); // this will actually execute the updates all in one
}
Run Code Online (Sandbox Code Playgroud)

这是做什么的:

  1. 预准备语句使SQL解析器只解析SQL一次
  2. 批处理最小化客户端 - 服务器 - 往返,以便每次更新都不会
  3. 客户端和服务器之间的通信被最小化,因为SQL只传输一次,数据被收集并作为数据包发送(或至少更少的数据包)

此外:

  • 请检查数据库列profileId是否正在使用索引,以便查找相应的行足够快
  • 您可以检查您的连接是否设置为自动提交.如果是这样,请尝试禁用自动提交并在更新所有行后显式提交事务.这样,单个更新操作也可以更快.