我需要更新超过 60k 行的表格的每一行。 目前我是这样做的:
public void updateRank(Map<Integer, Double> map) {
Iterator<Map.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();
}
}
仅此方法就需要大约 20 多分钟才能完成,我认为这里的每一行 (60k) 都会访问数据库。(尽管我使用 dbcp 进行连接池,最大 Activity 连接数为 50)
如果我能够通过单个数据库命中来更新行,那就太好了。那可能吗 ?怎么样?
或任何其他方法来改善这里的时间安排?
最佳答案
如果每一行都应该得到一个不同的值,而该值不能从数据库中的现有数据中派生出来,那么您就无法优化整体复杂性。所以不要期待太多奇迹。
也就是说,您应该开始使用准备好的语句和批处理:
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
}
这是做什么的:
- 预处理语句使SQL解析器只解析一次SQL
- 批处理最大限度地减少了客户端-服务器往返次数,因此不会每次更新都进行一次
- 客户端和服务器之间的通信被最小化,因为 SQL 只传输一次并且数据被收集并作为数据包(或至少更少的数据包)发送
此外:
- 请检查数据库列
profileId
是否正在使用索引,以便能够足够快地查找相应的行 - 您可以检查您的连接是否设置为自动提交。如果是这样,请尝试禁用自动提交并在更新所有行后显式提交事务。这样,单个更新操作也可以更快。
关于java - 更新单个表的多行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20354684/