我的地图中填充了大量数据(大约300,000条记录)
并按以下方式迭代,
for (Map.Entry<String, List<ClassOBj>> entry : testMap
.entrySet()) {
// send email with map keys as email'id
// email content is populated from the list
// Perform a sql update to the column with the dyanamic value generated here with the email'id
}
如上所述,我担心在for
循环内执行上述操作会导致性能问题。
更新
情景是。我正在迭代一个包含大量数据的地图,
在迭代它时,我得到用户ID,我必须计算用户ID。例如,考虑userid+some constants
,这应该在数据库表中更新。
也应该添加到电子邮件内容以及我的地图中的列表值
所以我认为批量更新是不可能的,我的理解是否正确?
我应该遵循这种方法吗?或者选择任何其他想法
答案 0 :(得分:2)
而不是在每个循环中更新数据库。尝试在完成循环后更新数据库。
优化大型数据库更新的方法有很多种。 最好的一个是
还使用基于线程的排队机制发送电子邮件
答案 1 :(得分:2)
由于两个原因,for循环需要时间 1)个人电子邮件通过减少运输连接来改善它 2)个人提交改进
所以理想的是处理两者,我建议你做1000批次,然后玩数字
示例
int BATCH_SIZE = 1000
conn = DriverManager.getConnection("username","password");
conn.setAutoCommit(false);
Statement stmt = conn.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
int count = 0;
Map<String, String> emails_map = new HashMap(BATCH_SIZE)<String, String>;
for (Map.Entry<String, List<ClassOBj>> entry : testMap
.entrySet()) {
String email = get_useremail();
String const_val = do_magic(); // this is how you are computing some constant
String body = construct_body();
count++;
String SQL = "YOUR UPDATE STATEMENT";
stmt.executeUpdate(SQL);
emails_map.put(email, body); // can create
if (count % BATCH_SIZE == 0) {
//commits all transcations
conn.commit();
//bulk send emails sending
//http://stackoverflow.com/questions/13287515/how-to-send-bulk-mails-using-javax-mail-api-efficiently-can-we-use-reuse-auth
bulk_emails_send(emails_map)
}
}
public void bulk_emails_send(Map<String, String> emails_map) {
// Get the default Session object through your setting
Session session = Session.getDefaultInstance(properties);
Transport t = session.getTransport();
t.connect();
try {
for (String email_id in emails_map) {
Message m = new MimeMessage(session);
//add to, from , subject, body
m.saveChanges();
t.sendMessage(m, m.getAllRecipients());
}
} finally {
t.close();
}
}
答案 2 :(得分:1)
我的建议是你可以使用Stored procedure
。或者使用可以使用批量更新代替此。
有关sql batch update的更多信息。
答案 3 :(得分:1)
您应该使用jdbc批量更新功能。
在迭代地图时,您可以将批处理添加到预准备语句中。当您添加(比方说)2000条记录时,您调用stmt.batchUpdate(),它将以快速方式更新2000条不同的记录。
您可以在此处看到一些示例:
http://www.mkyong.com/jdbc/jdbc-preparedstatement-example-batch-update/
第二件事 - 如果可以的话,在每个batchUpdate之后进行事务提交。对于数据库配置,300k记录的事务可能很多。将此更新拆分为多个事务将具有更好的性能 - 但前提是您不能在所有记录上进行事务处理。
答案 4 :(得分:1)
我会做这样的事情。准备操作数据。
我想您正在更新一个应该具有唯一ID的用户表。
Map<String, String> emailIds = new HashMap<String, String>();
Map<String, String> emails = new HashMap<String, String>();
for (Map.Entry<String, List<ClassOBj>> entry : testMap.entrySet()) {
-- DONOT DO THIS// send email with map keys as email'id
-- DONOT DO THIS// email content is populated from the list
-- DONOT DO THIS// Perform a sql update to the column with the dyanamic value generated here with the email'id
emails.put(emailId, content);
emailIds.put(id, emailId);
}
bulkEmailSend(emails);
bulkEmailUpdate(emailIds);
bulkEmailSend
和bulkEmailUpdate
是应该编写以进行适当调用的方法。
因此,使用批量电子邮件发送和批量emailId更新方法将值更新回数据库。
答案 5 :(得分:1)
我将尝试总结上面提到的所有优点。
您的选择是,
另一个不错的选择是使用批量更新,但批量更新会带来数据库端锁定时间更长的成本。所以明智地使用它,因为线程将等待一个线程完成更新,因为更新将采用独占锁定,即不可能共享。
尝试与异步作业一起进行线程处理(特别是对于邮件) 尝试使用不同的服务器/进程进行邮件处理并异步向邮件服务器发送邮件请求,这非常快,因为您的邮件生成任务由其他进程处理(在实际邮件交换中可以接受一些延迟,因此允许您的慢速邮件服务器但应用程序服务器不是。)
如果可能的话,在DB服务器上的存储过程中移动完整的Db更新逻辑,这将节省您的大量时间 (经验法则:总是让A处理设计/优化A的任务,即数据库设计用于比pgming语言更快的数据库操作。)
无法根据您的需要给出答案,但我希望这有助于改善它:)