Select com péssimo desempenho
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:
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]
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
Curtidas 0
Respostas
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
use
qual a versao do pg?
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
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:
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
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