2014-09-25 9 views
2

У меня есть карта с огромным количеством данных, заполняются (около 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.

Update:

сценарий. Я повторяю карту, которая содержит большой объем данных,

При повторении этого я получаю идентификатор пользователя, и я должен сделать вычисление идентификатора пользователя. Например, рассмотрим userid+some constants, и это должно быть обновлено в таблице базы данных ,

, а также должен быть добавлен к содержанию электронной почты вместе со значениями списка с моей карты

так я думал, что пакетные обновления не возможно, я правильно с моим пониманием?

Должен ли я следовать этому подходу? или пойти с любыми альтернативными идеями

+0

Идеальный сценарий - не делать дорогостоящие вызовы ресурсов - например, вызовы DB в цикле. Используйте промежуточные коллекции для хранения данных и использования массового обновления/массового удаления. Если это с 'Hibernate', сделайте' flush' после цикла. – VinayVeluri

+0

спасибо за ваше предложение. Как я объяснил выполненные операции. вы могли видеть, что массовые обновления не могут выполняться в качестве генерации значений dyanamic здесь –

+0

Создайте карту с ключом для хранения электронной почты и значения - если вам нужно какое-либо динамическое значение. Вместо того, чтобы выполнять обновление SQL, добавьте карту (хотя она динамическая, все значения, которые могут быть обновлены, будут на карте). Вы можете рассмотреть значения карт, которые могут быть обновлены напрямую. – VinayVeluri

ответ

2

для цикла принимает время по двум причинам: ,
1) Индивидуальный Email улучшить его связи менее транспорта
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(); 
    } 
} 
+0

любое обновление по этому вопросу? – mtariq

+0

Что такое 'do_magic()' метод, и вы также можете разработать отправку массовой почты и пакетного обновления –

+0

do_magic, как вы рассчитываете постоянную, объемное/пакетное обновление уже было там, а также добавлено массовое письмо – mtariq

1

Мое предложение вы можете использовать Stored procedure. или использование может использовать пакетное обновление вместо этого.

Подробнее о sql batch update.

1

Вы должны использовать функцию обновления партии jdbc.

При повторении по карте вы добавляете партию к своему подготовленному заявлению. Когда вы добавили (скажем) 2000 записей, вы вызываете stmt.batchUpdate(), который будет быстро обновлять 2000 разных записей.

Некоторые примеры вы можете увидеть здесь:

http://www.mkyong.com/jdbc/jdbc-preparedstatement-example-batch-update/

Вторая вещь - Если вы можете сделать транзакции после каждого batchUpdate. Транзакция для записей 300 тыс. Может быть значительной для вашей конфигурации базы данных. Разделение этого обновления на многие транзакции будет иметь лучшую производительность - но только если вы не можете иметь транзакцию по всем записям.

2

Вместо обновления базы данных в каждом цикле. Попробуйте обновить базу данных после завершения цикла.

Существует несколько способов оптимизации большого обновления базы данных. Лучший один из который

  • Вставьте измененные значения во временную таблицу
  • Update исходную таблицу из временной таблицы

Также используется механизм формирования очереди потоков на основе, чтобы отправить электронную почту

+0

спасибо за ваш ответ. Я обновил свой вопрос. надеюсь, что это ясно сейчас. можете ли вы помочь с дизайном высокого уровня? –

+0

Письмо во временную таблицу все равно будет препятствовать перфорации. поскольку он включает вызовы БД и дополнительно копирует данные в исходные таблицы. Это не то, что требуется. –

+0

@NachiketKate спасибо за ваше предложение. не стесняйтесь добавлять ответ, если у вас есть ответ :) –

1

Я бы сделал что-то вроде этого. Подготовьте данные для операции.

Я предполагаю, что вы обновляете таблицу, такую ​​как пользователь, который должен иметь уникальный идентификатор.

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 являются методы, которые должны быть написаны, чтобы сделать соответствующие вызовы.

Итак, используйте массовые методы отправки электронной почты и массового сообщения электронной почты для обновления значений обратно в базу данных.

1

Я попытаюсь обобщить все полезные моменты, упомянутые выше.

Ваши варианты,

  1. Использование многопоточности везде, где это возможно, но держать его в виду, что многопоточность поставляется со стоимостью дополнительной памяти (heapdumps и приложения будет вниз).
  2. Другим хорошим вариантом является массовое обновление, но снова массовое обновление поставляется со стоимостью большего времени блокировки в конце базы данных. поэтому используйте его разумно, поскольку потоки будут ждать, пока один поток не завершится с обновлением, так как обновление займет эксклюзивную блокировку, т. е. невозможно обмен.

  3. Попробуйте резьб в вместе с асинхронными рабочими местами (специально для почты) попытаться использовать другой сервер/процесс для обработки почты и отправка запросов почты на почтовый сервер асинхронно, который довольно быстро, как ваша задача генерации почты обрабатываются другим процесс (В реальной жизни почтовый обмен может принять некоторую задержку, поэтому ваш медленный почтовый сервер разрешен, но сервер приложений - нет.)

  4. Если возможно, переместите полную логику обновления Db в хранимую процедуру на сервере БД, что позволит сэкономить массу времени (Правило большого пальца: всегда разрешайте задачи дескриптора, для которых A спроектирован/оптимизирован ie DB предназначены для более быстрого DB o чем военные действия pgming языков.)

не могли бы дать вам ответить на конкретные ваши потребности, но я надеюсь, что это было полезно с точки зрения улучшения его :)

+0

Спасибо :). я постараюсь следовать вашим предложениям –

Смежные вопросы