SELECT MySQL muito lento! AJUDEM

Boa tarde pessoal estou desenvolvendo um relatório de despesas no Ireport com mysql, quando meus registros dos select´s internos são poucos ele surge rapidamente, mas quando passa de 100 o relatório demora quase meia hora para retornar apenas 3 páginas, segue abaixo o select.

select *,(select sum(cp.valSaldo) from CTAPAGAR cp where cp.NDOC=rp.NDOC ) as SALDOGERAL, (select sum(cp.valSaldo) from CTAPAGAR cp where cp.NDOC=rp.NDOC ) as SALDOAT, (select sum(cp.valPARC) from CTAPAGAR cp where cp.NDOC=rp.NDOC ) as TOTPAG from centro_de_custo cc, grupo g, despesa d,
ratctapag rp, fornecedor f, objeto o where
rp.codccusto = cc.cod_c_custo and
d.cod_grupo = g.cod_grupo and rp.codforn = f.codigo and
rp.codgrupo = g.cod_grupo and
rp.coddespesa = d.cod_despesa and rp.codobjeto=o.codigo order by cc.cod_c_custo asc, g.cod_grupo asc,
d.cod_despesa asc, rp.ndoc asc

Tem alguma forma de melhorar esse select para agilizar???
No aguardo,
Att. Murilo.

murilomenegasso,

  1. Já rodou esta query em algum frontend de banco para ver se o tempo é alto também?
  2. Realmente você precisa Select *?

Antes de mais nada, NÃO CRIE TÓPICOS COM TÍTULOS EM LETRAS MAIÚSCULAS.
Nem com ajudem, help, please, socorro e afins.

Depois, leia http://guj.com.br/java/50115-voce-e-novo-no-guj-vai-criar-um-topico-e-colar-seu-codigo-fonte-leia-aqui-antes-por-favor.

Primeiramente, já conhece algo chamado join? Cairia bem e evitaria esta lentidão.
Segundo

SELECT *, ...

Camarada, a não ser que esta tabela possua 2 colunas e não possua mais de 10 linhas, não se deve utilizar * numa consulta. Independente de ter 10 ou 1000 colunas, o ideal é colocar o nome de todas (ou apenas aquelas que irá utilizar realmente).

Boa tarde.

Cara evite usar CROSS JOIN http://en.wikipedia.org/wiki/Join_(SQL)

Monta a sua consulta usando inner join, left join etc.

Tentando entender a sua consulta montei essa aqui com inner join:

select *, (select sum(cp.valSaldo) from CTAPAGAR cp where cp.NDOC=rp.NDOC ) as SALDOGERAL, (select sum(cp.valSaldo) from CTAPAGAR cp where cp.NDOC=rp.NDOC ) as SALDOAT, (select sum(cp.valPARC) from CTAPAGAR cp where cp.NDOC=rp.NDOC ) as TOTPAG from centro_de_custo cc inner join ratctapag rp on rp.codccusto = cc.cod_c_custo inner join grupo g on rp.codgrupo = g.cod_grupo inner join despesa d on d.cod_grupo = g.cod_grupo and rp.coddespesa = d.cod_despesa inner join fornecedor f on rp.codforn = f.codigo inner join objeto o on rp.codobjeto = o.codigo order by cc.cod_c_custo asc, g.cod_grupo asc, d.cod_despesa asc, rp.ndoc asc

Até a leitura fica mais facil.

Vamos ver se baixa o tempo

drsmachado,

Concordo contigo em relação ao “select *”.

Em relação aos joins, quando você comparação da tabela filha com a tabela mãe dentro da clausula where você tem melhor performance do que join próprio, pois você deixa o SGBD definir o melhor join para aquela consulta.

[ ]'s

[quote=BMuniz]drsmachado,

Concordo contigo em relação ao “select *”.

Em relação aos joins, quando você comparação da tabela filha com a tabela mãe dentro da clausula where você tem melhor performance do que join próprio, pois você deixa o SGBD definir o melhor join para aquela consulta.

[ ]'s[/quote]

Não vi em nenhum lugar um relacionamento de herança…

Obrigado “Oliveira.caio”, segui seu exemplo e funcionou perfeitamente, agora o relatório é apresentado em no máximo 2 segundos!!!

Obrigado a todos que ajudaram tbm.

Att. Murilo!

Acho que alem dos joins voce poderia , juntar as 3 subqueries em uma assim:

select * ,(select sum(cp.valSaldo) as SALDOGERAL , sum(cp.valSaldo) as SALDOAT , sum(cp.valPARC)  as TOTPAG  from CTAPAGAR cp where cp.NDOC=rp.NDOC )
from centro_de_custo cc,
  inner join ratctapag rp on rp.codccusto = cc.cod_c_custo
  inner join grupo g on rp.codgrupo = g.cod_grupo 
  inner join despesa d on d.cod_grupo = g.cod_grupo and rp.coddespesa = d.cod_despesa
  inner join fornecedor f on rp.codforn = f.codigo
  inner join objeto o on rp.codobjeto = o.codigo 
order by cc.cod_c_custo asc,
	g.cod_grupo asc,
	d.cod_despesa asc,
	rp.ndoc asc 

ou entao dividir a query em duas:

select * ,
from centro_de_custo cc,
  inner join ratctapag rp on rp.codccusto = cc.cod_c_custo
  inner join grupo g on rp.codgrupo = g.cod_grupo 
  inner join despesa d on d.cod_grupo = g.cod_grupo and rp.coddespesa = d.cod_despesa
  inner join fornecedor f on rp.codforn = f.codigo
  inner join objeto o on rp.codobjeto = o.codigo
order by cc.cod_c_custo asc,
	g.cod_grupo asc,
	d.cod_despesa asc,
	rp.ndoc asc 
select sum(cp.valSaldo) as SALDOGERAL , sum(cp.valSaldo) as SALDOAT , sum(cp.valPARC)  as TOTPAG 
 from CTAPAGAR cp,
ratctapag rp
 where cp.NDOC=rp.NDOC 

outra coisa pela sua queri notei que SALDOGERAL é calculado da mesma forma que SALDOAT voce poderia calcular na query apenas um deles.

Você tem razão “marciavilaca”, acertei esses detalhes!

Obrigado!