Então, sua pergunta finalmente se resume a "como
java.sql.PreparedStatement
joga com o PostgreSQL." Veja a resposta em "como isso funciona com os planos preparados pelo servidor" no final. Aqui está a resposta:isso depende do driver JDBC que você usa.
TL;DR :em drivers modernos, a instrução preparada pelo servidor vive até que a conexão morra ou até que a instrução seja despejada por outra (remoção de LRU regular).
Nota:O servidor PostgreSQL não pode compartilhar instruções preparadas em conexões de banco de dados, portanto, o melhor driver JDBC que pode fazer é manter o plano armazenado em cache em cada conexão.
Observação:a especificação JDBC exige o uso de
?, ?
para marcadores de vínculo, enquanto o servidor deseja $1, $2
assim, os drivers JDBC também armazenam os chamados textos SQL analisados. Existem dois drivers JDBC conhecidos:pgjdbc e pgjdbc-ng
pgjdbc
https://github.com/pgjdbc/pgjdbc
Desde pgjdbc 9.4-1202 ele armazena automaticamente os planos do lado do servidor ao usar
PreparedStatement
.Nota:as instruções são armazenadas em cache mesmo se você close()
a PreparedStatement
.Para chegar à preparação do lado do servidor, você precisa executar a consulta 5 vezes (que pode ser configurada via prepareThreshold
). Atualmente, o cache é implementado por conexão. Por padrão, o pgjdbc armazena em cache 256 (
preparedStatementCacheQueries
) e até preparedStatementCacheSizeMiB
de consultas. Esta é uma configuração conservadora, então você pode querer ajustá-la. Consulte a documentação
para a descrição das propriedades. O cache inclui instruções analisadas e preparadas pelo servidor. problema do github:https://github.com/pgjdbc/pgjdbc/pull/319
pgjdbc-ng
https://github.com/impossibl/pgjdbc-ng
Eu não gosto de pgjdbc-ng, no entanto, parece que ele faz a análise (o tamanho padrão do cache é 250 consultas) e preparação do servidor (o tamanho padrão do cache é 50 consultas). O suporte de instruções preparadas do lado do servidor chegou em 24 de fevereiro de 2014, portanto, se você usar uma versão um pouco recente, poderá obter o cache de instruções.
Nota:se você acidentalmente usar consultas muito longas, você pode clicar em
OutOfMemory
já que o pgjdbc-ng não pode remover entradas com base no número de bytes retidos. O cache é por conexão, portanto, é usado de forma transparente mesmo se você fechar instruções.
Não posso dizer muito sobre o desempenho do pgjdbc-ng, embora desde a última vez que tentei jogar o jmh nele, ele falhou com exceções aleatórias.
problema do github:https://github.com/impossibl/pgjdbc-ng/pull/ 69
Planos preparados para servidor
PostgreSQL tem
PREPARE
e DEALLOCATE
comandos para referenciar a instrução ao enviar EXEC
sobre o fio. Ele otimiza duas coisas:- Ao usar
PREPARE
d (em outras palavras, preparada pelo servidor), o cliente não precisa enviar o texto da consulta repetidamente. Ele apenas envia um nome de consulta curto e os valores para variáveis de ligação. - Desde 9.2, o banco de dados ainda tenta replanejar as primeiras execuções de uma consulta. Ele faz isso para testar se a consulta precisa de vários planos ou se o plano genérico é bom o suficiente. Eventualmente (imediatamente se a consulta não tiver parâmetros), o banco de dados pode mudar para um plano genérico .
- Desde 12, há uma configuração para forçar TODAS as instruções preparadas pelo servidor a serem executadas com planos genéricos ou personalizados:plan_cache_mode
=
auto | force_custom_plan | force_generic_plan
Em outras palavras,
PreparedStatement
otimiza tanto a análise de consulta no lado do JDBC quanto o planejamento de consulta no lado do banco de dados. Mais informações aqui:http://blog.endpoint .com/2014/04/custom-plans-prepared-statements-in.html
Declarações preparadas em PL/pgSQL
De acordo com a documentação, PostgreSQL caches planos para consultas usadas em PL/pgSQL. Isso acontece após algumas execuções (3 ou 5, não me lembro do limite exato), portanto, depois de criar o procedimento armazenado, ele pode ficar um pouco lento, no entanto, ele alternará para os planos em cache (desde que o banco de dados concorde em usar o plano genérico para uma consulta específica).
Em outras palavras, para obter "planos de execução em cache", você precisa usar o driver JDBC atualizado ou pode agrupar todas as suas consultas em procedimentos armazenados. normalmente muito mais curtas do que as consultas que compõem o procedimento.