Mysql
 sql >> Database >  >> RDS >> Mysql

Qual è la differenza tra cachePrepStmts e useServerPrepStmts nel driver MySQL JDBC

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.