insert d'hibernation haute performance
Je suis en train de travailler sur un temps de latence partie sensible d'une application, en gros je vais recevoir un événement sur le réseau de transformer les données, puis de les insérer toutes les données dans la DB. Après avoir établi le profil je vois que, fondamentalement, tout mon temps est consacré à essayer de sauver les données. voici le code
private void insertAllData(Collection<Data> dataItems)
{
long start_time = System.currentTimeMillis();
long save_time = 0;
long commit_time = 0;
Transaction tx = null;
try
{
Session s = HibernateSessionFactory.getSession();
s.setCacheMode(CacheMode.IGNORE);
s.setFlushMode(FlushMode.NEVER);
tx = s.beginTransaction();
for(Data data : dataItems)
{
s.saveOrUpdate(data);
}
save_time = System.currentTimeMillis();
tx.commit();
s.flush();
s.clear();
}
catch(HibernateException ex)
{
if(tx != null)
tx.rollback();
}
commit_time = System.currentTimeMillis();
System.out.println("Save: " + (save_time - start_time));
System.out.println("Commit: " + (commit_time - save_time));
System.out.println();
}
La taille de la collection est toujours inférieur à 20. voici les données de temps que je vois:
Save: 27
Commit: 9
Save: 27
Commit: 9
Save: 26
Commit: 9
Save: 36
Commit: 9
Save: 44
Commit: 0
C'est confus pour moi. Je me figure que le save
devrait être rapide et de tous les temps devrait être consacré à commit
. mais il est clair que je me trompe. J'ai également essayé de supprimer la transaction (ce n'est pas vraiment nécessaire), mais j'ai vu pire des fois... j'ai mis en veille prolongée.jdbc.batch_size=20...
Je peux attendre pour obtenir autant que 500 messages/sec donc j'ai besoin unique de gestion de messages à moins de 20 millisecondes.
j'ai besoin de cette opération pour être aussi rapide que possible, idéalement, il serait seulement un aller-retour à la base de données. Comment puis-je faire cela?
source d'informationauteur luke
Vous devez vous connecter pour publier un commentaire.
Déplacer votre clé primaire une génération à l'écart à partir d'un serveur de côté l'auto-incrémentation. Votre code Java doit être responsable de la PK génération pour éviter les allers-retours.
Décent bulk insert de performance, vous avez besoin d'une méthode qui ne sera pas besoin de toucher la base de données sur chaque appel à saveOrUpdate. À l'aide des Uuid que la clé primaire, ou la mise en œuvre de HiLo peut aider à atteindre cet objectif. Sinon, il n'y a pas d'insertion en bloc.
D'avoir à la fois les performances et l'interopérabilité avec d'autres systèmes externes, les commun ou la mis en commun-lo optimiseurs sont le meilleur choix.
Honnêtement, je ne sais pas ce qui peut être raisonnablement conclu, à partir de votre test et de la "mesure" dont vous faites preuve (je soupçonne beaucoup de frais généraux de l'échauffement, la collection est très petite, et l'échantillon est très petit).
De toute façon, je peux vous dire que votre code ne sera pas à l'échelle et vous êtes très probablement faire exploser la Session lors du passage d'un plus grand collection. Vous devez rincer et effacer la séance à intervalles réguliers (chaque 20 dossiers si la taille du lot est de 20).
En fait, je recommande la lecture de l'ensemble de la Le chapitre 13. Le traitement par lot.
Quelques trucs de base:
contraintes avec aucun indice?
Le traitement par lots est une partie de JDBC 2.0, il vous permet d'exécuter plusieurs instructions dans un "lot"; l'idée est de réduire la latence d'aller-retour (vous pouvez exécuter plusieurs lots par transaction).
Vous pouvez probablement utiliser cela comme un test de référence. Je voudrais aussi regarder le SQL que hibernate génère, pour voir si c'est l'exécution d'une requête par l'insertion d'obtenir l'Id générés.