Tout d'abord, il est important de faire la distinction entre les instructions préparées par le client et par le serveur.
Relevés préparés par le client
Les relevés préparés par le client sont des relevés préparés "émulés". Cela signifie que la chaîne de l'instruction SQL est tokenisée côté client et que tous les espaces réservés sont remplacés par des valeurs littérales avant d'envoyer l'instruction au serveur pour exécution. Une instruction SQL complète est envoyée au serveur à chaque exécution. Vous pouvez utiliser le journal général pour étudier comment cela fonctionne. ex.
le code suivant :
ps=conn.prepareStatement("select ?")
ps.setInt(1, 42)
ps.executeQuery()
ps.setInt(1, 43)
ps.executeQuery()
s'afficherait dans le journal :
255 Query select 42
255 Query select 43
La "requête" indique qu'au niveau du protocole, un COM_QUERY
la commande est envoyée avec la chaîne d'instruction suivante.
Relevés préparés par le serveur
Les instructions préparées par le serveur sont de "vraies" instructions préparées, ce qui signifie que le texte de la requête est envoyé au serveur, analysé, et que les informations d'espace réservé et de résultat sont renvoyées au client. C'est ce que vous obtenez en définissant useServerPrepStmts=true
. La chaîne d'instruction n'est envoyée au serveur qu'une seule fois avec un COM_STMT_PREPARE
appel (documenté ici
). Chaque exécution est effectuée en envoyant un COM_STMT_EXECUTE
avec le handle d'instruction préparé et les valeurs littérales à remplacer pour les espaces réservés.
Pour contraster avec l'exemple préparé par le client, nous pouvons utiliser un bloc de code similaire (mais cette fois avec les instructions préparées par le serveur activées) :
ps2=conn2.prepareStatement("select ?")
ps2.setInt(1, 42)
ps2.executeQuery()
ps2.setInt(1, 43)
ps2.executeQuery()
Et le journal afficherait :
254 Prepare select ?
254 Execute select 42
254 Execute select 43
Vous pouvez voir que l'instruction est préparée avant d'être exécutée. Le journal nous rend service et affiche l'instruction complète pour l'exécution mais, en fait, seules les valeurs d'espace réservé sont envoyées du client au serveur pour chaque exécution.
Mise en cache des instructions préparées
De nombreux pools de connexions mettront en cache les instructions préparées à travers les utilisations d'une connexion, ce qui signifie que si vous appelez conn.prepareStatement("select ?")
, il renverra le même PreparedStatement
instance lors d'appels successifs avec la même chaîne d'instruction. Ceci est utile pour éviter de préparer plusieurs fois la même chaîne sur le serveur lorsque les connexions sont renvoyées au pool entre les transactions.
L'option MySQL JDBC cachePrepStmts
mettra en cache les instructions préparées de cette manière (instructions préparées par le client et le serveur) ainsi que la "préparabilité" d'une instruction. Certaines instructions de MySQL ne peuvent pas être préparées côté serveur. Le pilote essaiera de préparer une instruction sur le serveur s'il pense que c'est possible et, si la préparation échoue, reviendra à une instruction préparée par le client. Cette vérification est coûteuse car elle nécessite un aller-retour vers le serveur. L'option mettra également en cache le résultat de cette vérification.
J'espère que cela vous aidera.