PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Compréhension des opérations par lots JDBC

Il peut y avoir différents types de traitement par lots impliqués, et j'en couvrirais une partie du pilote PostgreSQL JDBC (pgjdbc).

TL; DR :pgjdbc utilise moins d'allers-retours réseau dans le cas où l'API batch est utilisée. BatchedQuery est utilisé uniquement si reWriteBatchedInserts=true est transmis aux paramètres de connexion pgjdbc.

Vous pourriez trouver https://www.slideshare.net/VladimirSitnikv/postgresql-and-jdbc-striving-for-high-performance pertinent (diapositive 44,...)

En ce qui concerne l'exécution des requêtes, la latence du réseau représente souvent une part importante du temps écoulé.

Supposons que le cas consiste à insérer 10 lignes.

  1. Pas de traitement par lot (par exemple, juste PreparedStatement#execute en boucle). Le conducteur effectuerait ce qui suit

    execute query
    sync <-- wait for the response from the DB
    execute query
    sync <-- wait for the response from the DB
    execute query
    sync <-- wait for the response from the DB
    ...
    

    Un temps notable serait passé dans "l'attente de la BD"

  2. API batch JDBC. C'est PreparedStatement#addBatch() permet au pilote d'envoyer plusieurs "exécutions de requêtes" dans un seul aller-retour réseau. La mise en œuvre actuelle, cependant, diviserait toujours les gros lots en plus petits pour éviter les blocages TCP.

    Les actions seraient bien meilleures :

    execute query
    ...
    execute query
    execute query
    execute query
    sync <-- wait for the response from the DB
    
  3. Notez que même avec #addBatch , il y a une surcharge des commandes "exécuter la requête". Cela prend un temps considérable au serveur pour traiter chaque message individuellement.

    L'un des moyens de réduire le nombre de requêtes consiste à utiliser l'insertion multi-valeurs. Par exemple :

    insert into tab(a,b,c) values (?,?,?), (?,?,?), ..., (?,?,?)
    

    Ce PostgreSQL permet d'insérer plusieurs lignes à la fois. L'inconvénient est que vous n'avez pas de message d'erreur détaillé (par ligne). Actuellement, Hibernate n'implémente pas l'insertion multi-valeurs.

    Cependant, pgjdbc peut réécrire à la volée les insertions de lots régulières en multi-valeurs depuis 9.4.1209 (2016-07-15).

    Afin d'activer la réécriture multi-valeurs, vous devez ajouter reWriteBatchedInserts=true propriété de connexion. La fonctionnalité a été initialement développée dans https://github.com/pgjdbc/pgjdbc/pull/491

    Il est assez intelligent d'utiliser 2 instructions pour insérer 10 lignes. Le premier est un énoncé à 8 valeurs et le second est un énoncé à 2 valeurs. L'utilisation de puissances de deux permet à pgjdbc de conserver le nombre d'instructions distinctes, ce qui améliore les performances car les instructions souvent utilisées sont préparées par le serveur (voir Quelle est la durée de vie d'une instruction préparée côté serveur PostgreSQL )

    BatchedQuery représente ce type d'instructions à plusieurs valeurs, vous verrez donc cette classe utilisée dans reWriteBatchedInserts=true cas uniquement.

    Les inconvénients de la fonctionnalité peuvent inclure :des détails inférieurs au "résultat du lot". Par exemple, un lot régulier vous donne "par nombre de lignes d'instruction", mais dans le cas de plusieurs valeurs, vous obtenez simplement le statut "instruction terminée". En plus de cela, la réécriture à la volée peut ne pas réussir à analyser certaines instructions SQL (par exemple, https://github.com/pgjdbc/pgjdbc/issues/1045 ).