PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Quando as consultas (SELECT) são planejadas?


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.