Först är det viktigt att skilja mellan klient- och serverförberedda uttalanden.
Klientförberedda uttalanden
Klientförberedda uttalanden är "emulerade" förberedda uttalanden. Detta innebär att SQL-satssträngen tokeniseras på klientsidan och eventuella platshållare ersätts med bokstavliga värden innan satsen skickas till servern för exekvering. En komplett SQL-sats skickas till servern vid varje körning. Du kan använda den allmänna loggen för att undersöka hur detta fungerar. t.ex.
följande kod:
ps=conn.prepareStatement("select ?")
ps.setInt(1, 42)
ps.executeQuery()
ps.setInt(1, 43)
ps.executeQuery()
skulle visa i loggen:
255 Query select 42
255 Query select 43
"Frågan" indikerar att, på protokollnivå, en COM_QUERY
kommandot skickas med satssträngen efter.
Serverförberedda uttalanden
Serverförberedda påståenden är "sanna" förberedda påståenden, vilket betyder att frågetexten skickas till servern, analyseras och platshållare och resultatinformation returneras till klienten. Detta är vad du får när du ställer in useServerPrepStmts=true
. Uttryckssträngen skickas bara en gång till servern med en COM_STMT_PREPARE
samtal (dokumenterat här
). Varje körning utförs genom att skicka en COM_STMT_EXECUTE
med det förberedda uttalshandtaget och de bokstavliga värdena för att ersätta platshållarna.
Som kontrast till det klientförberedda exemplet kan vi använda ett liknande kodblock (men den här gången med serverförberedda satser aktiverade):
ps2=conn2.prepareStatement("select ?")
ps2.setInt(1, 42)
ps2.executeQuery()
ps2.setInt(1, 43)
ps2.executeQuery()
Och loggen skulle visa:
254 Prepare select ?
254 Execute select 42
254 Execute select 43
Du kan se att uttalandet är förberett innan det körs. Loggen gör oss en tjänst och visar hela uttalandet för körningen, men i själva verket skickas endast platshållarvärdena från klient till server för varje körning.
Cacha förberedda uttalanden
Många anslutningspooler cachelagrar förberedda uttalanden över användningar av en anslutning, vilket innebär att om du anropar conn.prepareStatement("select ?")
, kommer det att returnera samma PreparedStatement
instans på successiva anrop med samma uttalande sträng. Detta är användbart för att undvika att förbereda samma sträng på servern upprepade gånger när anslutningar returneras till poolen mellan transaktioner.
MySQL JDBC-alternativet cachePrepStmts
kommer att cache förberedda satser på detta sätt (både klient- och serverförberedda satser) samt cachelagra "förberedbarheten" för en sats. Det finns vissa uttalanden i MySQL som inte går att förbereda på serversidan. Drivrutinen kommer att försöka förbereda en sats på servern om den tror att det är möjligt och, om prepareringen misslyckas, falla tillbaka till en klientförberedd sats. Denna check är dyr på grund av att den kräver en tur och retur till servern. Alternativet cachelagrar också resultatet av denna kontroll.
Hoppas detta hjälper.