Я столкнулся с проблемой производительности моего пакетного задания, написанного с использованием JPA (с использованием OpenJPA), которое работает как простое Java-приложение.Я пытаюсь вставить огромный список объектов, например, более 10 миллионов записей.Я знаю, что этот дизайн не является правильным.Но я получу этот объем данных внезапно, и я не смогу разделить всю работу.
Я разделил список с подсписками размером 100 000 каждый.И я вызываю метод транзакции JPA для каждого из этого подсписка.В каждой такой транзакции я очищаю список, когда он достигает 2000. Насколько я понимаю, для 1 миллиона записей он совершает 100 транзакционных вызовов.
Как только работа началась, я увидел, что 6 миллионов записей вставляются в течение 15-20 минут, а среднее время составляет всего одну минуту для 300 000. Но после того, как оно достигло 6-6,5 миллионов, работа выполняется очень медленноПримерно 10 тысяч за 4-6 минут, ощущение остановилось.Но он продолжает работать, и нет недостатка памяти в куче.
Может кто-нибудь сказать, что ошибка в моем коде.Я пробовал с разными размерами чанка (25K, 50K, 100K) для подсписка.Я не понимаю, чем вызвана эта медлительность после середины Иова.Должен ли я очищать EM после каждой транзакции?Я также увеличил размер пула соединений.
Вот мой код:
@Stateless()
@LocalBean
@TransactionAttribute(TransactionAttributeType.NEVER)
public class BatchService{
@EJB
private PersonService personService;
public void run(List<Person> personList) {
int totalEventSize = personList.size();
int quotient = totalEventSize / 100000;
int modulo = totalEventSize % 100000;
int totalIterations = quotient + (modulo != 0 ? 1 : 0);
int startCount = 0;
int endCount = 0;
for (int i = 1; i <= totalIterations; i++) {
if (i == totalIterations) {
endCount = totalEventSize;
} else {
endCount = startCount + 100000;
}
List<Person> subList = personList.subList(startCount, endCount);
personService.create(subList);
startCount = endCount;
}
}
}
@Stateless
@LocalBean
public class PersonService implements Serializable {
@EJB
private PersonDLService personDLService;
public void create(List<Person> list) {
try {
personDLService.createPerson(list);
} catch (RuntimeException e) {
e.printStackTrace();
}
}
}
@Stateless
@LocalBean
@TransactionAttribute(TransactionAttributeType.MANDATORY)
public class PersonDLService implements Serializable {
private static final long serialVersionUID = 1L;
@PersistenceContext(unitName = Constants.PERSISTENCE_UNIT_NAME)
private transient EntityManager entityManager;
public void createPerson(List<Person> personObj) {
for (int i = 0; i < personObj.size(); i++) {
entityManager.persist(personObj.get(i));
if (i % 2000 == 0) {
entityManager.flush();
entityManager.clear();
}
}
System.out.println("***************** COMMITED ****************" + personObj.size());
}
}