J'ai une application web qui reçoit des messages via une interface HTTP, par exemple:insertion par lots en utilisant JPA/Toplink
http://server/application?source=123&destination=234&text=hello
Cette demande contient l'ID de l'expéditeur, l'ID du destinataire et le texte de la message.
Ce message doit être traité comme:
- trouver le correspondant objet utilisateur à la fois la source et la destination de la base de données
- créer un arbre d'objets: un message qui contient un champ pour le message text et deux objets Utilisateur pour la source et la destination
- persistant cet arbre à une base de données.
L'arborescence sera chargée par d'autres applications que je ne peux pas toucher. J'utilise Oracle comme base de données de sauvegarde et JPA avec Toplink pour les tâches de gestion de base de données. Si possible, je resterais avec ceux-ci.
Sans beaucoup d'optimisation, je peux atteindre ~ 30 requêtes/s de débit dans mon environnement. Ce n'est pas beaucoup, j'aurais besoin de ~ 300 demandes/sec. J'ai donc mesuré où le goulot d'étranglement de la performance est et a constaté que les appels à em.persist()
prend la plupart du temps. Si je commente simplement cette ligne, le débit va bien au-delà de 1000 requêtes/sec.
J'ai essayé d'écrire une petite application de test qui utilisait de simples appels JDBC pour conserver 1 million de messages dans la même base de données. J'ai utilisé le batching, ce qui signifie que j'ai fait 100 insertions puis commit, et répété jusqu'à ce que tous les enregistrements soient dans la base de données. J'ai mesuré ~ 500 demandes/s de débit dans ce scénario, ce qui répondrait à mes besoins.
Il est clair que j'ai besoin d'optimiser les performances d'insertion ici. Cependant, comme je l'ai mentionné plus tôt, je voudrais continuer à utiliser JPA et Toplink pour cela, pas JDBC pur.
Connaissez-vous un moyen de créer des insertions par lots avec JPA et Toplink? Pouvez-vous recommander n'importe quelle autre technique pour améliorer la performance de persistance de JPA?
INFO ADDITIONNELLE:
"demandes/sec" signifie ici: nombre total de demandes/temps total depuis le début du test dernier enregistrement par écrit à la base de données.
J'ai essayé de rendre les appels à em.persist()
asynchrones en créant une file d'attente en mémoire entre le contenu de la servlet et le persister. Cela a grandement aidé la performance. Cependant, la file d'attente s'est développée très rapidement et comme l'application recevra ~ 200 requêtes/seconde en continu, ce n'est pas une solution acceptable pour moi.
Dans cette approche découplée, j'ai collecté des requêtes pendant 100 msec et j'ai appelé em.persist()
sur tous les éléments collectés avant de valider la transaction. EntityManagerFactory est mis en cache entre chaque transaction.
Merci, je vais essayer dans quelques jours. Qu'entendez-vous par taille de séquençage? – Zizzencs