Zunächst ist es wichtig, zwischen vom Client und vom Server vorbereiteten Anweisungen zu unterscheiden.
Vom Kunden vorbereitete Erklärungen
Vom Client vorbereitete Anweisungen sind "emulierte" vorbereitete Anweisungen. Dies bedeutet, dass die SQL-Anweisungszeichenfolge auf der Clientseite in Tokens umgewandelt wird und alle Platzhalter durch Literalwerte ersetzt werden, bevor die Anweisung zur Ausführung an den Server gesendet wird. Bei jeder Ausführung wird eine vollständige SQL-Anweisung an den Server gesendet. Sie können das allgemeine Protokoll verwenden, um zu untersuchen, wie dies funktioniert. z. B.
folgenden Code:
ps=conn.prepareStatement("select ?")
ps.setInt(1, 42)
ps.executeQuery()
ps.setInt(1, 43)
ps.executeQuery()
würde im Log erscheinen:
255 Query select 42
255 Query select 43
Die "Abfrage" gibt an, dass auf Protokollebene ein COM_QUERY
Der Befehl wird mit der folgenden Anweisungszeichenfolge gesendet.
Vom Server vorbereitete Anweisungen
Vom Server vorbereitete Anweisungen sind "wahre" vorbereitete Anweisungen, was bedeutet, dass der Abfragetext an den Server gesendet, analysiert und Platzhalter- und Ergebnisinformationen an den Client zurückgegeben werden. Das erhalten Sie, wenn Sie useServerPrepStmts=true
setzen . Der Anweisungsstring wird immer nur einmal mit einem COM_STMT_PREPARE
an den Server gesendet aufrufen (dokumentiert hier
). ). Jede Ausführung wird durch Senden eines COM_STMT_EXECUTE
durchgeführt mit dem Handle der vorbereiteten Anweisung und den Literalwerten, die die Platzhalter ersetzen sollen.
Als Kontrast zum vom Client vorbereiteten Beispiel können wir einen ähnlichen Codeblock verwenden (jedoch dieses Mal mit aktivierten vom Server vorbereiteten Anweisungen):
ps2=conn2.prepareStatement("select ?")
ps2.setInt(1, 42)
ps2.executeQuery()
ps2.setInt(1, 43)
ps2.executeQuery()
Und das Protokoll würde zeigen:
254 Prepare select ?
254 Execute select 42
254 Execute select 43
Sie können sehen, dass die Anweisung vorbereitet wird, bevor sie ausgeführt wird. Das Protokoll tut uns einen Gefallen und zeigt die vollständige Anweisung für die Ausführung, aber tatsächlich werden nur die Platzhalterwerte für jede Ausführung vom Client zum Server gesendet.
Vorbereitete Anweisungen zwischenspeichern
Viele Verbindungspools speichern vorbereitete Anweisungen über die Verwendung einer Verbindung hinweg, was bedeutet, dass Sie conn.prepareStatement("select ?")
aufrufen , wird dasselbe PreparedStatement
zurückgegeben Instanz bei aufeinanderfolgenden Aufrufen mit derselben Anweisungszeichenfolge. Dies ist nützlich, um zu vermeiden, dass dieselbe Zeichenfolge wiederholt auf dem Server erstellt wird, wenn Verbindungen zwischen Transaktionen an den Pool zurückgegeben werden.
Die MySQL-JDBC-Option cachePrepStmts
speichert vorbereitete Anweisungen auf diese Weise (sowohl vom Client als auch vom Server vorbereitete Anweisungen) sowie die "Vorbereitbarkeit" einer Anweisung. Es gibt einige Anweisungen in MySQL, die serverseitig nicht vorbereitet werden können. Der Treiber wird versuchen, eine Anweisung auf dem Server vorzubereiten, wenn er dies für möglich hält, und, wenn die Vorbereitung fehlschlägt, auf eine vom Client vorbereitete Anweisung zurückgreifen. Diese Prüfung ist teuer, da ein Roundtrip zum Server erforderlich ist. Die Option speichert auch das Ergebnis dieser Prüfung.
Hoffe das hilft.