Pessoal,

Eu imagino ter participado da discussão ocorrida "há um tempo atrás" e é claro que como já fui e muitas vezes continuo sendo vítima de planos mal escolhidos tenho um detalhe a acrescentar:

Um servidor Dell PowerEdge 1800, dual zeon, 4GB, 4 hds SAS em raid 10 executou uma consulta que mostra o valor faturado em 40 impressoras fiscais em um único dia classificado por impressora fiscal em uns 4 a 5 minutos.

Um desktop core2duo, 4GB, 1 hd sata2 executou a mesma consulta sobre um backup do primeiro equipamento restaurado no segundo em 1segundo.

Os planos de execução são muitíssimo diferentes e comparando o postgres.conf de cada um, respectivamente, temos as seguintes diferenças principais:

max_connections =           70       100
shared_buffers =          1000MB      32MB
work_mem =                  64MB       1MB
maintenance_work_mem =     256MB      16MB
max_fsm_pages =        1000000    324000
checkpoint_segments =        3        10
effective_cache_size =     256MB     128M


Nas próximas semanas pretendo realizar novos testes, mas não é a primeira vez que vejo isto e por isto se vê tanto ajuste pelo método de tentativa e erro.

Abraços,


Mozart Hasse escreveu:
Euler,

Eu escrevi:
  
No meu caso o que sempre fez e continua fazendo uma falta desgraçada no
Postgres é um otimizador decente (...) Bem que se podia aproveitar a
      
idéia aplicada no
  
Oracle ou no SQL Server e ter um cache de planos (...)
      

  
Isso já existe: chama-se comandos preparados (aka _prepared statements_).
    

Isso ??!
http://jdbc.postgresql.org/documentation/83/server-prepare.html

Não, não estou falando de algo tão simplório. Prepared statements têm
diversas desvantagens em relação ao que o Oracle e o SQL Server fazem:

* Prepared statements funcionam dentro da mesma conexão. Logo, consultas
idênticas feitas por instâncias diferentes da mesma aplicação ou
aplicações diferentes que façam as mesmas consultas continuarão tendo um
custo alto recompilando dúzias de vezes os mesmos comandos. Isso, é claro,
assumindo que eu me dê ao trabalho de mexer na minha aplicação para fazer
todas as consultas através da mesma conexão. O ganho disso seria bastante
questionável considerando que isso implica em serializar operações que
podem correr em paralelo.

* Da documentação:
"(...)
Server side prepared statements are planned only once by the server. This
avoids the cost of replanning the query every time, but also means that the
planner cannot take advantage of the particular parameter values used in a
particular execution of the query. 
(...)"
Logo, Prepared statements usam o mesmo plano independente dos valores, o que
resulta em desastre. Isso é exatamente o *oposto* do que se espera de um
otimizador decente. O otimizador deveria ter uma lista de planos para a mesma
consulta e usar o mais adequado para cada uma.

  
É claro que você precisa manter a conexão mas nada que um aglomerador de
conexões (aka _pool_) não resolva.
    

Como expus acima, fazer isso, ainda por cima em larga escala, resulta em
desastre.

  
Como você mesmo disse, o tempo é relativamente pequeno em aplicações Web
    
e
  
OLTP; em OLAP, algumas consultas com dezenas de junções esse tempo é
significativo (aumenta 2^n mas é para isso que temos o GEQO) mas mesmo
    
assim
  
bem inferior ao de execução da consulta.
    

Dezenas de junções não são exclusividade de aplicações OLAP, muito pelo
contrário.
O fato de uma consulta cheia de junções exigir um enorme tempo de
planejamento de forma alguma implica em não valer a pena gastá-lo fazendo
isso. É exatamente nessas tabelas potencialmente grandes e cheias de índices
que uma escolha errada do otimizador resulta em planos catastróficos.
 
  
É fácil falar do otimizador mas é difícil mexer nele. ;)
    

Ora, ora, pelo menos nisso concordamos integralmente. A pergunta do tópico
foi quanto ao que se poderia melhorar em desempenho, só estou expondo a lista
para resolver os *meus* problemas. Afinal, custa-me acreditar que sou o único
interessado em desempenho por aqui.

  
Já tivemos essa discussão a um tempo atrás (...). Se eu me lembro bem,
    
nenhuma das
  
consultas apresentadas por você produzia um plano que não era ideal.
    

Depende do que chamarmos de "ideal". Para mim o ideal é medir as consultas em
milissegundos para poder comparar com Oracle e SQL Server, e não em minutos.
OK, de fato não tenho no momento exemplos usando a última versão do
Postgres, quando tiver passo para a lista. Fazer testes comparativos de
desempenho é algo que consome tempo que é dificílimo de conseguir
considerando nossas experiências anteriores.

Atenciosamente,


Mozart Hasse


_______________________________________________
pgbr-geral mailing list
[email protected]
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

  

-- 
Sergio Medeiros Santi
_______________________________________________
pgbr-geral mailing list
[email protected]
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Responder a