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

Quelle est la durée de vie d'une instruction préparée côté serveur PostgreSQL

Donc, votre question se résume finalement à "comment java.sql.PreparedStatement joue avec PostgreSQL". Voir la réponse sur "comment cela joue avec les plans préparés par le serveur" à la fin.

Voici la réponse :cela dépend du pilote JDBC que vous utilisez.

TL;DR  :dans les pilotes modernes, l'instruction préparée par le serveur vit jusqu'à ce que la connexion meure ou jusqu'à ce que l'instruction soit expulsée par une autre (expulsion LRU régulière).

Remarque :Le serveur PostgreSQL ne peut pas partager les instructions préparées entre les connexions à la base de données. Le meilleur pilote JDBC est donc de conserver le plan en cache dans chaque connexion.

Remarque :la spécification JDBC impose l'utilisation de ?, ? pour les espaces réservés de liaison, tandis que le serveur veut $1, $2 ainsi, les pilotes JDBC mettent également en cache les textes SQL dits analysés.

Il existe deux pilotes JDBC bien connus :pgjdbc et pgjdbc-ng

pgjdbc

https://github.com/pgjdbc/pgjdbc

Depuis pgjdbc 9.4-1202 il met automatiquement en cache les plans côté serveur lors de l'utilisation de PreparedStatement .Remarque :les instructions sont mises en cache même si vous close() le PreparedStatement .Pour accéder à la préparation côté serveur, vous devez exécuter la requête 5 fois (configurable via prepareThreshold ).

Actuellement, le cache est implémenté par connexion. Par défaut, pgjdbc met en cache 256 (preparedStatementCacheQueries ) requêtes et jusqu'à preparedStatementCacheSizeMiB de requêtes. Il s'agit d'un paramètre conservateur, vous voudrez peut-être l'ajuster. Voir la documentation pour la description des propriétés. Le cache comprend à la fois des instructions analysées et préparées par le serveur.

problème github :https://github.com/pgjdbc/pgjdbc/pull/319

pgjdbc-ng

https://github.com/impossibl/pgjdbc-ng

Je ne suis pas dans pgjdbc-ng, mais il semble qu'il effectue les deux analyses (la taille de cache par défaut est 250 requêtes) et la préparation du serveur (la taille du cache par défaut est 50 requêtes). La prise en charge des instructions préparées côté serveur a atterri le 24 février 2014, donc si vous utilisez une version assez récente, vous pouvez obtenir la mise en cache des instructions.

Remarque :si vous utilisez accidentellement des requêtes très longues, vous pouvez appuyer sur OutOfMemory puisque pgjdbc-ng ne peut pas supprimer les entrées en fonction du nombre d'octets retenus.

Le cache est par connexion, il est donc utilisé de manière transparente même si vous fermez des instructions.

Je ne peux pas dire grand-chose sur les performances de pgjdbc-ng, bien que depuis la dernière fois que j'ai essayé de lancer jmh, il a échoué avec des exceptions aléatoires.

problème github :https://github.com/impossibl/pgjdbc-ng/pull/ 69

Plans préparés par le serveur

PostgreSQL a PREPARE et DEALLOCATE commandes pour référencer l'instruction lors de l'envoi de EXEC sur le fil. Il optimise deux choses :

  1. Lors de l'utilisation de PREPARE d (en d'autres termes, une instruction préparée par le serveur), le client n'a pas à envoyer le texte de la requête encore et encore. Il envoie simplement un nom de requête court et les valeurs des variables de liaison.
  2. Depuis la version 9.2, la base de données essaie toujours de replanifier les premières exécutions d'une requête. Il le fait pour essayer si la requête nécessite plusieurs plans ou si le plan générique est suffisant. Finalement (immédiatement si la requête n'a pas de paramètres), la base de données peut passer à un forfait générique .
  3. Depuis la version 12, un paramètre force l'exécution de TOUTES les instructions préparées par le serveur avec des plans génériques ou personnalisés :plan_cache_mode =auto | force_custom_plan | force_generic_plan

En d'autres termes, PreparedStatement optimise à la fois l'analyse des requêtes côté JDBC et la planification des requêtes côté base de données.

Plus d'informations ici :http://blog.endpoint .com/2014/04/custom-plans-prepared-statements-in.html

Déclarations préparées en PL/pgSQL

Selon la documentation, PostgreSQL caches plans pour les requêtes utilisées en PL/pgSQL. Cela se produit après quelques exécutions (3 ou 5, je ne me souviens pas du seuil exact), donc après avoir créé une procédure stockée, cela peut être un peu lent, mais il passera ensuite aux plans en cache (à condition que la base de données accepte d'utiliser le plan générique pour une requête particulière).

En d'autres termes, pour réaliser des "plans d'exécution en cache", vous devez soit utiliser un pilote JDBC à jour, soit vous pouvez encapsuler toutes vos requêtes dans des procédures stockées. L'appel à la procédure sera replanifié à chaque exécution, mais l'appel lui-même est généralement beaucoup plus court que les requêtes qui composent la procédure.