我需要更新行数超过6万的表的每一行。 目前我这样做 -
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();
}
}
仅此方法需要大约20分钟才能完成,每行(60k)命中数据库就是我认为的原因。(虽然我使用dbcp进行连接池,最多有50个活动连接)
如果我能够使用单个数据库命中更新行,那就太好了。那可能吗 ?怎么样?
或者其他任何改善时间的方法?
答案 0 :(得分: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
}
这是做什么的:
另外:
profileId
是否正在使用索引,以便查找相应的行足够快答案 1 :(得分:2)
您可以连接查询(用;
分隔)并仅发送100个查询批量。
public void updateRank(Map<Integer,Double> map){
Iterator<Entry<Integer, Double>> it = map.entrySet().iterator();
String queries = "";
int i = 0;
while (it.hasNext()) {
Map.Entry<Integer,Double> pairs = (Map.Entry<Integer,Double>)it.next();
queries += "update profile set rank = "+ pairs.getValue()+ " where profileId = "+pairs.getKey() + ";";
it.remove();
if(i++ % 100 == 99){
DBUtil.update(queries);
queries = "";
}
}
}
答案 2 :(得分:2)
现在您独立执行每个查询会导致巨大的连接开销(即使使用连接池)。而是使用批处理机制一起执行多个查询。
使用JDBC(DBCP显然正在使用)和准备好的语句,您可以使用addBatch()
和executeBatch()
轻松完成此操作。我最近不得不自己做这件事,批量大约1000个查询是最快的。虽然在你的情况下这可能完全不同。
<强>参考强>