Não posso falar sobre a interface Perl do lado do cliente em si, mas posso esclarecer o lado do servidor PostgreSQL.
O PostgreSQL preparou declarações e declarações não preparadas. Instruções não preparadas são analisadas, planejadas e executadas imediatamente. Eles também não suporte a substituição de parâmetros. Em um
psql
simples shell, você pode mostrar o plano de consulta assim:tmpdb> explain select * from sometable where flag = true;
Por outro lado, existem instruções preparadas:elas são geralmente (veja "exceção" abaixo) analisadas e planejadas em uma etapa e executadas em uma segunda etapa. Eles podem ser executados várias vezes com parâmetros diferentes, porque eles fazem suporte a substituição de parâmetros. O equivalente em
psql
é isto:tmpdb> prepare foo as select * from sometable where flag = $1;
tmpdb> explain execute foo(true);
Você pode ver que o plano é diferente do plano na declaração despreparada, porque o planejamento já ocorreu no
prepare
fase conforme descrito no documento para PREPARAR
:Isso também significa que o plano NÃO otimizado para os parâmetros substituídos:Nos primeiros exemplos pode-se usar um índice para
flag
porque o PostgreSQL sabe que dentro de um milhão de entradas apenas dez têm o valor true
. Esse raciocínio é impossível quando o PostgreSQL usa uma instrução preparada. Nesse caso, é criado um plano que funcionará para todos os valores de parâmetros possíveis da melhor maneira possível. Isso pode exclua o índice mencionado porque buscar a melhor parte da tabela completa via acesso aleatório (devido ao índice) é mais lento do que uma varredura sequencial simples. O PREPARAR
doc confirma isso:BTW - Em relação ao cache do plano PREPARE doc também tem algo a dizer:
Também não há cache de plano automático e nem cache/reutilização em várias conexões.
EXCEÇÃO :eu mencionei "geralmente". O
psql
mostrado exemplos não são as coisas que um adaptador cliente como Perl DBI realmente usa. Ele usa um certo protocolo
. Aqui o termo "consulta simples" corresponde à "consulta não preparada" em psql
, o termo "consulta estendida " corresponde a "consulta preparada" com uma exceção:há uma distinção entre (uma) "declaração sem nome" e (possivelmente várias) "declarações com nome". Em relação a declarações com nome, a doc
diz:e também:
Portanto, neste caso, o planejamento é feito sem parâmetros, conforme descrito acima para
PREPARE
- nada de novo. A exceção mencionada é a "declaração sem nome". O doc diz:
E aqui está o benefício:embora a instrução sem nome esteja "preparada" (ou seja, possa ter substituição de parâmetro), ela também pode adaptar o plano de consulta aos parâmetros reais.
BTW:O tratamento exato da instrução sem nome mudou várias vezes nas versões anteriores do servidor PostgreSQL. Você pode pesquisar os documentos antigos para obter detalhes, se realmente quiser.
Racional - Perl / qualquer cliente :
Como um cliente como Perl usa o protocolo é uma questão completamente diferente. Alguns clientes como o driver JDBC para Java basicamente dizem:Mesmo que o programador use uma instrução preparada, as primeiras cinco (ou mais) execuções são mapeadas internamente para uma "consulta simples" (ou seja, efetivamente despreparada), depois disso o driver muda para " declaração nomeada".
Portanto, um cliente tem essas opções:
- Force (re)planejamento a cada vez usando o protocolo de "consulta simples".
- Plano uma vez, execute várias vezes usando o protocolo "consulta estendida" e a "instrução nomeada" (o plano pode ser ruim porque o planejamento é feito sem parâmetros).
- Analisar uma vez, planeje cada execução (com a versão atual do PostgreSQL) usando o protocolo "extended query" e a "instrução sem nome" e obedecendo a mais algumas coisas (forneça alguns parâmetros durante a mensagem "parse")
- Jogue truques completamente diferentes, como o driver JDBC.
O que Perl faz atualmente:Não sei. Mas o mencionado "arenque vermelho" não é muito improvável.