Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 提高此场景性能的方法_Java_Performance_For Loop_Map - Fatal编程技术网

Java 提高此场景性能的方法

Java 提高此场景性能的方法,java,performance,for-loop,map,Java,Performance,For Loop,Map,我有一张包含大量数据的地图(大约300000条记录) 并按如下所示进行迭代 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 upd

我有一张包含大量数据的地图(大约300000条记录)

并按如下所示进行迭代

    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(Map.Entry:testMap
.entrySet()){
//将地图键作为电子邮件id发送电子邮件
//从列表中填充电子邮件内容
//使用此处生成的带有email'id的动态值对列执行sql更新
}
如上所述,我担心在
for
循环中执行上述操作会导致性能问题

更新:

情况是这样的。我正在迭代一个包含大量数据的地图

迭代时,我得到用户ID,我必须计算用户ID。例如,考虑<代码> USERID +一些常量< /代码>,这应该在数据库表中更新。< /P> 也应该与我的地图中的列表值一起添加到电子邮件内容中

所以我认为批量更新是不可能的,我的理解正确吗


我应该遵循这种方法吗?或者使用其他方法

我的建议是您可以使用
存储过程
。或者可以使用批处理更新来代替此


更多信息。

您应该使用jdbc批量更新功能

在映射上迭代时,将批处理添加到准备的语句中。添加(比如)2000条记录后,调用stmt.batchUpdate(),它将快速更新2000条不同的记录

您可以在此处看到一些示例:


第二件事——如果可以的话,在每次批处理更新之后进行事务提交。300k记录的事务可能对您的数据库配置影响很大。将此更新拆分为多个事务将具有更好的性能—但前提是您不能在所有记录上都有事务。

而不是在每个循环中更新数据库。请在完成循环后尝试更新数据库

有不同的方法来优化大型数据库更新。 其中最好的一个就是

  • 将修改后的值插入临时表
  • 从临时表更新原始表

还可以使用基于线程的排队机制发送电子邮件

我会这样做。为操作准备数据

我假设您正在更新一个类似user的表,它应该具有唯一的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);
Map emailIds=newhashmap();
Map emails=newhashmap();
for(Map.Entry:testMap.entrySet()){
--请勿执行此操作//将地图键作为电子邮件id发送电子邮件
--请勿执行此操作//从列表中填充电子邮件内容
--不要这样做//使用此处生成的带有email'id的动态值对列执行sql更新
emails.put(emailId、内容);
emailId.put(id,emailId);
}
电子邮件发送(电子邮件);
批量电子邮件更新(EmailID);
bulkEmailSend
bulkEmailUpdate
是进行适当调用时应该编写的方法


因此,使用批量电子邮件发送和批量电子邮件ID更新方法将值更新回数据库。

我将尝试总结上面提到的所有优点

你的选择是

  • 尽可能使用多线程,但请记住,多线程会带来额外内存的开销(堆转储和应用程序将停止运行)
  • 另一个好的选择是使用批量更新,但批量更新同样会在数据库端花费更多的锁定时间。因此,明智地使用它,因为线程将等待一个线程完成更新,因为更新将采用独占锁,即不可能共享

  • 尝试在异步作业中加入线程(特别是邮件) 尝试使用不同的服务器/进程进行邮件处理,并将邮件请求异步发送到邮件服务器,这相当快,因为您的邮件生成任务是由其他进程处理的(在现实生活中,邮件交换可能会接受一些延迟,因此允许使用较慢的邮件服务器,但不允许使用应用程序服务器)

  • 如果可能的话,在Db服务器上的存储过程中移动完整的Db更新逻辑,这将节省大量时间 (经验法则:始终让A处理设计/优化了A的任务,即DB设计用于比pgming语言更快的DB操作。)


  • 无法针对您的需求给出具体的答案,但我希望这对改进它有所帮助:)

    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();
        }
    }
    
    int批大小=1000
    conn=DriverManager.getConnection(“用户名”、“密码”);
    连接设置自动提交(错误);
    语句stmt=conn.createStatement(
    ResultSet.TYPE\u SCROLL\u不敏感,
    结果集CONCUR_可更新);
    整数计数=0;
    Map email\u Map=新HashMap(批大小);
    对于(Map.Entry:testMap
    .entrySet()){
    字符串email=get_useremail();
    String const_val=do_magic();//这就是计算常数的方法
    字符串体=构造体();
    计数++;
    String SQL=“您的更新语句”;
    stmt.executeUpdate(SQL);
    emails_map.put(email,body);//可以创建
    如果(计数%BATCH_SIZE==0){
    //提交所有转换
    conn.commit();
    //批量发送电子邮件发送
    //http://stackoverflow.com/questions/13287515/how-to-send-bulk-mails-using-javax-mail-api-efficiently-can-we-use-reuse-auth
    批量发送电子邮件(电子邮件地图)
    }
    }
    公共无效批量电子邮件发送(映射电子邮件映射){
    //通过设置获取默认会话对象
    Session Session=Session.getDefaultInstance(属性);
    Transport t=session.getTransport();
    t、 connect();
    试一试{
    对于(ema中的字符串电子邮件\u id)