我需要更新超过 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 进行连接池,最大活动连接数为 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
使用索引,以便查找相应的行足够快
- 您可以检查您的连接是否设置为自动提交。如果是这样,请尝试禁用自动提交并在更新所有行后显式提交事务。这样单个更新操作也可以更快。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)