For det første er det vigtigt at skelne mellem klient- og serverforberedte erklæringer.
Kundeforberedte erklæringer
Klientudarbejdede udsagn er "emulerede" udarbejdede udsagn. Dette betyder, at SQL-sætningsstrengen tokeniseres på klientsiden, og eventuelle pladsholdere erstattes med bogstavelige værdier, før sætningen sendes til serveren til udførelse. En komplet SQL-sætning sendes til serveren ved hver udførelse. Du kan bruge den generelle log til at undersøge, hvordan dette fungerer. f.eks.
følgende kode:
ps=conn.prepareStatement("select ?")
ps.setInt(1, 42)
ps.executeQuery()
ps.setInt(1, 43)
ps.executeQuery()
ville vise i loggen:
255 Query select 42
255 Query select 43
"Forespørgslen" angiver, at der på protokolniveau er en COM_QUERY
kommandoen sendes med sætningsstrengen efter.
Serverforberedte erklæringer
Serverforberedte udsagn er "sande" forberedte udsagn, hvilket betyder, at forespørgselsteksten sendes til serveren, parses, og pladsholder- og resultatoplysninger returneres til klienten. Dette er, hvad du får, når du indstiller useServerPrepStmts=true
. Udsagnsstrengen sendes kun til serveren én gang med en COM_STMT_PREPARE
opkald (dokumenteret her
). Hver udførelse udføres ved at sende en COM_STMT_EXECUTE
med det forberedte udsagnshåndtag og de bogstavelige værdier til at erstatte pladsholderne.
I modsætning til det klientforberedte eksempel kan vi bruge en lignende kodeblok (men denne gang med serverforberedte sætninger aktiveret):
ps2=conn2.prepareStatement("select ?")
ps2.setInt(1, 42)
ps2.executeQuery()
ps2.setInt(1, 43)
ps2.executeQuery()
Og loggen ville vise:
254 Prepare select ?
254 Execute select 42
254 Execute select 43
Du kan se, at erklæringen er udarbejdet, inden den udføres. Loggen gør os en tjeneste og viser den komplette erklæring for udførelsen, men faktisk er det kun pladsholderværdierne, der sendes fra klient til server for hver kørsel.
Caching af forberedte udsagn
Mange forbindelsespuljer cachelagrede forberedte udsagn på tværs af anvendelser af en forbindelse, hvilket betyder, at hvis du kalder conn.prepareStatement("select ?")
, vil det returnere det samme PreparedStatement
instans på successive opkald med den samme sætningsstreng. Dette er nyttigt for at undgå at forberede den samme streng på serveren gentagne gange, når forbindelser returneres til puljen mellem transaktioner.
MySQL JDBC-indstillingen cachePrepStmts
vil cache forberedte udsagn på denne måde (både klient- og serverforberedte udsagn) samt cache "forberedeligheden" af en udsagn. Der er nogle udsagn i MySQL, som ikke kan forberedes på serversiden. Driveren vil forsøge at forberede en erklæring på serveren, hvis den mener, det er muligt, og hvis forberedelsen mislykkes, falde tilbage til en klientforberedt erklæring. Denne check er dyr, fordi den kræver en rundtur til serveren. Indstillingen vil også cache resultatet af denne kontrol.
Håber dette hjælper.