Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Qual é a diferença entre cachePrepStmts e useServerPrepStmts no MySQL JDBC Driver


Primeiro, é importante distinguir entre as instruções preparadas pelo cliente e pelo servidor.

Declarações preparadas pelo cliente


As declarações preparadas pelo cliente são declarações preparadas "emuladas". Isso significa que a string da instrução SQL é tokenizada no lado do cliente e quaisquer espaços reservados são substituídos por valores literais antes de enviar a instrução ao servidor para execução. Uma instrução SQL completa é enviada ao servidor em cada execução. Você pode usar o log geral para investigar como isso funciona. por exemplo.

o seguinte código:
ps=conn.prepareStatement("select ?")
ps.setInt(1, 42)
ps.executeQuery()
ps.setInt(1, 43)
ps.executeQuery()

mostraria no log:
255 Query  select 42
255 Query  select 43

A "consulta" indica que, no nível do protocolo, um COM_QUERY O comando é enviado com a string de instrução a seguir.

Declarações preparadas pelo servidor


As instruções preparadas pelo servidor são instruções preparadas "verdadeiras", o que significa que o texto da consulta é enviado para o servidor, analisado e reservado, e as informações do resultado são retornadas ao cliente. Isso é o que você obtém ao definir useServerPrepStmts=true . A string de instrução só é enviada ao servidor uma vez com um COM_STMT_PREPARE call (documentado aqui ). Cada execução é realizada enviando um COM_STMT_EXECUTE com o identificador de instrução preparado e os valores literais para substituir os espaços reservados.

Para contrastar com o exemplo preparado pelo cliente, podemos usar um bloco de código semelhante (mas desta vez com instruções preparadas pelo servidor habilitadas):
ps2=conn2.prepareStatement("select ?")
ps2.setInt(1, 42)
ps2.executeQuery()
ps2.setInt(1, 43)
ps2.executeQuery()

E o log mostraria:
254 Prepare    select ?
254 Execute    select 42
254 Execute    select 43

Você pode ver que a instrução é preparada antes de ser executada. O log está nos fazendo um favor e mostrando a instrução completa para a execução, mas, na verdade, apenas os valores do placeholder são enviados do cliente para o servidor para cada execução.

Armazenamento de Declarações Preparadas em Cache


Muitos pools de conexão armazenarão em cache as instruções preparadas nos usos de uma conexão, o que significa que, se você chamar conn.prepareStatement("select ?") , ele retornará o mesmo PreparedStatement instância em chamadas sucessivas com a mesma string de instrução. Isso é útil para evitar preparar a mesma string no servidor repetidamente quando as conexões são retornadas ao pool entre transações.

A opção MySQL JDBC cachePrepStmts armazenará em cache as instruções preparadas dessa maneira (tanto as instruções preparadas pelo cliente quanto pelo servidor), bem como armazenará em cache a "preparabilidade" de uma instrução. Existem algumas instruções no MySQL que não são preparáveis ​​no lado do servidor. O driver tentará preparar uma instrução no servidor se acreditar que é possível e, se a preparação falhar, retornará a uma instrução preparada pelo cliente. Essa verificação é cara devido à necessidade de uma viagem de ida e volta ao servidor. A opção também armazenará em cache o resultado dessa verificação.

Espero que isto ajude.