У меня есть веб-приложение, которое получает сообщения через интерфейс HTTP, например:Пакетная вставка с использованием JPA/Toplink
http://server/application?source=123&destination=234&text=hello
Этот запрос содержит идентификатор отправителя, идентификатор получателя и текст из сообщение.
Это сообщение должно быть обработано как:
- найти соответствующий объект пользователя для источника и назначения из базы данных
- создает дерево объектов: Сообщение, содержащее поле для сообщения текст и два объекта пользователя для источника и адресата
- сохранение этого дерева в базе данных.
Дерево будет загружено другими приложениями, к которым я не могу прикасаться.
Я использую Oracle как базу данных поддержки и JPA с помощью Toplink для задач обработки базы данных. Если возможно, я останусь с ними.
Без большой оптимизации я могу достичь ~ 30 запросов/сек пропускной способности в моей среде. Это не так много, я бы потребовал ~ 300 запросов/сек. Поэтому я измерил, где узкое место производительности и обнаружил, что звонки на em.persist()
занимают большую часть времени. Если я просто прокомментирую эту строку, пропускная способность пройдет более 1000 запросов/сек.
Я попытался написать небольшое тестовое приложение, которое использовало простые вызовы JDBC для сохранения 1 миллиона сообщений в одной и той же базе данных. Я использовал пакетную обработку, то есть я сделал 100 вставок, затем фиксацию, и повторил, пока все записи не были в базе данных. В этом сценарии я измерил ~ 500 запросов в секунду, что соответствовало бы моим потребностям.
Понятно, что мне нужно оптимизировать производительность вставки здесь. Однако, как я упоминал ранее, я хотел бы использовать JPA и Toplink для этого, а не чистый JDBC.
Знаете ли вы способ создания пакетных вставок с JPA и Toplink? Можете ли вы порекомендовать какой-либо другой метод повышения производительности JPA?
ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ:
«запросы/сек» означает здесь: общее количество запросов/общее время от начала испытания до последней прочитанной записи в базу данных.
Я попытался сделать асинхронный вызов em.persist()
, создав очередь в памяти между материалом сервлета и персистом. Это очень помогло выходу. Однако очередь действительно быстро развивалась, и когда приложение будет получать ~ 200 запросов в секунду, это не приемлемое решение для меня.
В этом отцепленном подходе я собрал запросы на 100 мс и вызвал em.persist()
по всем собранным элементам до совершения транзакции. EntityManagerFactory кэшируется между каждой транзакцией.
Спасибо, я попробую это через несколько дней. Что вы имеете в виду о размере последовательности? – Zizzencs