Innanzitutto, è importante distinguere tra istruzioni preparate per client e server.
Dichiarazioni preparate dal cliente
Le dichiarazioni preparate dal cliente sono dichiarazioni preparate "emulate". Ciò significa che la stringa dell'istruzione SQL viene tokenizzata sul lato client e tutti i segnaposto vengono sostituiti con valori letterali prima di inviare l'istruzione al server per l'esecuzione. Un'istruzione SQL completa viene inviata al server ad ogni esecuzione. È possibile utilizzare il registro generale per indagare su come funziona. es.
il seguente codice:
ps=conn.prepareStatement("select ?")
ps.setInt(1, 42)
ps.executeQuery()
ps.setInt(1, 43)
ps.executeQuery()
mostrerebbe nel registro:
255 Query select 42
255 Query select 43
La "query" indica che, a livello di protocollo, un COM_QUERY
il comando viene inviato con la seguente stringa di istruzioni.
Dichiarazioni preparate dal server
Le istruzioni preparate dal server sono istruzioni preparate "vere", il che significa che il testo della query viene inviato al server, analizzato e le informazioni sui segnaposto e sui risultati vengono restituite al client. Questo è ciò che ottieni quando imposti useServerPrepStmts=true
. La stringa dell'istruzione viene inviata al server solo una volta con un COM_STMT_PREPARE
chiama (documentato qui
). Ogni esecuzione viene eseguita inviando un COM_STMT_EXECUTE
con l'handle dell'istruzione preparata e i valori letterali da sostituire ai segnaposto.
In contrasto con l'esempio preparato dal client, possiamo utilizzare un blocco di codice simile (ma questa volta con le istruzioni preparate dal server abilitate):
ps2=conn2.prepareStatement("select ?")
ps2.setInt(1, 42)
ps2.executeQuery()
ps2.setInt(1, 43)
ps2.executeQuery()
E il registro mostrerebbe:
254 Prepare select ?
254 Execute select 42
254 Execute select 43
Puoi vedere che l'istruzione viene preparata prima di essere eseguita. Il log ci sta facendo un favore e mostra l'istruzione completa per l'esecuzione ma, in effetti, solo i valori segnaposto vengono inviati dal client al server per ogni esecuzione.
Memorizzazione nella cache delle istruzioni preparate
Molti pool di connessioni memorizzano nella cache le istruzioni preparate durante gli usi di una connessione, il che significa che se chiami conn.prepareStatement("select ?")
, restituirà lo stesso PreparedStatement
istanza su chiamate successive con la stessa stringa di istruzioni. Ciò è utile per evitare di preparare ripetutamente la stessa stringa sul server quando le connessioni vengono restituite al pool tra le transazioni.
L'opzione MySQL JDBC cachePrepStmts
memorizzerà nella cache le istruzioni preparate in questo modo (dichiarazioni preparate sia dal client che dal server), nonché memorizzando nella cache la "preparabilità" di un'istruzione. Ci sono alcune istruzioni in MySQL che non sono preparabili lato server. Il conducente proverà a preparare una dichiarazione sul server se lo ritiene possibile e, se la preparazione non riesce, ricadrà su una dichiarazione preparata dal client. Questo controllo è costoso perché richiede un viaggio di andata e ritorno al server. L'opzione memorizzerà nella cache anche il risultato di questo controllo.
Spero che questo aiuti.