Select com péssimo desempenho

PostgreSQL

22/08/2008

Olá pessoal,

estou fazendo uma migração de um software que era em Delphi + SQL Server e que está indo para Java + PostgreSQL.

Está ocorrendo uma diferença muito grande de desempenho entre os dois bancos.

Tenho uma consulta, que no SQL roda em menos de 10s, enquanto no postgre chega a demorar 11 minutos.

Fiquei muito assustado, pois nunca tinha visto tamanho problema de desempenho em fóruns ou qualquer coisa do tipo. É justamente o contrário, sempre ouvi falar muito bem do Postgre.

A consulta que estou tentando fazer é essa daqui:

SELECT 
SUM(bd.quantidade) 
FROM 
basedadocusto bd 
WHERE 
bd.lancamento IN 
(SELECT 
bdqtde.lancamento 
FROM 
basedadocusto bdqtde  
INNER JOIN basedadocustoexecutante beqtde ON (beqtde.codcarga = bdqtde.codcarga AND beqtde.lancamento = bdqtde.lancamento)  
INNER JOIN prestador executanteqtde ON (executanteqtde.codprestador = beqtde.codexecutante) 
INNER JOIN categoriaprestador categoriaexecutanteqtde ON (categoriaexecutanteqtde.codcategoriaprestador = beqtde.codcategoriaexecutante) 
WHERE 
bdqtde.codcarga = bd.codcarga AND 
bdqtde.lancamento = bd.lancamento 
)


Na verdade isso é só parte de uma consulta maior, mas é esse pedaço que não quer rodar.

Só pra adiantar umas coisas:
- já rodei o vacuum full
- os dois bancos possuem os mesmo índices
- os dois bancos possuem a mesma quantidade de dados
- os testes foram feitos na mesma máquina (Core 2 Duo 2.2, 2GB, Win XP)
- essa consulta pode parecer estranha, mas realmente tem a necessidade de ser assim, pois como eu disse, é só um pedaço de uma maior

Desde já, agradeço[/code]


Victorfugiwara

Victorfugiwara

Curtidas 0

Respostas

Comodelphi

Comodelphi

22/08/2008

realmente a consulta ta estranha, mas se tem que ser assim, você pode tentar usar o explain para ver se os indices estao sendo usados, também ajuda se voce usar o ANALYZE depois do VACUUM.

Tem varias situacoes em que uso sub-queries nos meu projetos, sem maiores problemas. Talvez seja interessante vc personalizar os parametros de desempenho e memória no seu postgres.

E ainda poderia trocar no seu select ao invés de
bd.lancamento IN


use

exists


qual a versao do pg?


GOSTEI 0
Victorfugiwara

Victorfugiwara

22/08/2008

O pg é a versão 8.3

Criei alguns índices a mais e consegui baixar para cerca de 5 minutos a consulta.

Vou colocar a consulta inteira aqui:

SELECT 
dados.codigo AS Codigo, 
dados.nome AS Nome, 
dados.outro AS Outro, 
dados.notas AS Notas, 
dados.qtde AS Servicos, 
dados.pacientes AS Pacientes, 
(dados.qtde / dados.pacientes) AS ServicoPaciente, 
(dados.custo / dados.notas) AS CustoNota, 
(dados.custo / dados.qtde) AS CustoServico, 
(dados.custo / dados.pacientes) AS CustoPaciente, 
dados.custo AS CustoTotal 
FROM 
(SELECT 
executante.codprestador AS Codigo, 
executante.nome AS Nome, 
´´ AS Outro, 
COUNT(DISTINCT basedadocusto.nota) AS notas, 
COUNT(DISTINCT basedadocusto.codbeneficiario) AS pacientes, 
SUM(basedadocustoexecutante.custo) AS custo, 
(SELECT 
SUM(bd.quantidade) 
FROM 
basedadocusto bd 
WHERE 
bd.lancamento IN (
SELECT 
bdqtde.lancamento 
FROM 
basedadocusto bdqtde  
LEFT OUTER JOIN basedadocustoexecutante beqtde ON (beqtde.codcarga = bdqtde.codcarga AND beqtde.lancamento = bdqtde.lancamento) 
INNER JOIN beneficiario beneficiarioqtde ON (beneficiarioqtde.codbeneficiario = bdqtde.codbeneficiario) 
INNER JOIN prestador executanteqtde ON (executanteqtde.codprestador = beqtde.codexecutante) 
WHERE 
bdqtde.codcarga = bd.codcarga AND 
executanteqtde.codprestador = executante.codprestador AND 
(  beneficiarioqtde.sexo = ´M´ AND  
bdqtde.formacobranca = ´C´ AND  
bdqtde.regulamentado = ´N´ AND  
beqtde.situacaopagamento = ´P´ AND  
bdqtde.postoatendimento = ´0´ )
)
) AS qtde 
FROM 
basedadocusto 
LEFT OUTER JOIN basedadocustoexecutante ON (basedadocustoexecutante.codcarga = basedadocusto.codcarga AND basedadocustoexecutante.lancamento = basedadocusto.lancamento) 
INNER JOIN beneficiario ON (beneficiario.codbeneficiario = basedadocusto.codbeneficiario) 
INNER JOIN prestador executante ON (executante.codprestador = basedadocustoexecutante.codexecutante) 
WHERE 
(  beneficiario.sexo = ´M´ AND  
basedadocusto.formacobranca = ´C´ AND  
basedadocusto.regulamentado = ´N´ AND  
basedadocustoexecutante.situacaopagamento = ´P´ AND  
basedadocusto.postoatendimento = ´0´ ) 
GROUP BY 
executante.codprestador, 
executante.nome
) AS dados  
ORDER BY 
CustoTotal Desc



colocando o exists, ficou pior (não imagino o porque).
rodei o ANALYZE também, mas não vi muita diferença.
na primeira mensagem coloquei só aquela parte da frase por ser onde se concentra a demora, mas talvez possa ajudar colocando tudo assim.

Obrigado


GOSTEI 0
POSTAR