Problema de desempenho com jasperreport, o que seria melhor?

18 respostas
AnjoVingador

Bom pessoal como está escrito no título, estamos enfrentando este tipo de problema aqui na empresa.
Os relatórios são grandes o maior tem 1669 páginas com várias colunas, mas o problema que leva, aqui na empresa, 26 segundos mais ou menos para gerar e no cliente demora mais ainda.
Esta demora não está agradando.
Bom estamos passando a query no xml e deixando o relatório fazer as consultas no banco de dados, são várias querys no mesmo relatório.
Bom como eu poderia resolver isso?
Passando os abjetos ao invés das querys?Seria mais rápido assim?E se for mais rápido, qual seria a diferença baseado no tempo que falei acima?
Gostaria de saber pois, tenho que ter certeza antes de sugerir isso para equipe, pois é uma mudança considerável e se for feita atoa as coisas não ficariam boas pra mim, hehehehe.
A aplicação é web, usa JSF + PrimeFaces + DB4O , mas as consultas dos relatórios são feitas em um banco relacional, e roda debaixo do tomcat 7.
Aguardo reposta.
Desde já agradeço.

18 Respostas

Giulliano

na boa…NINGUÉM lê um relatório de 1.000+ páginas com trocentas colunas.

AnjoVingador

Giulliano:
na boa…NINGUÉM lê um relatório de 1.000+ páginas com trocentas colunas.

Eu sei que ninguém lê, mas tem que ser gerado, mesmo que não seja todo lido, mas alguém pode querer uma página lá no meio ou no final.
Ta bom eu exagerei nas colunas, são 10 no máximo, mas o número de páginas é 1669 mesmo.
Você tem alguma sugestão?

blackout

Antes de pensarmos numa solução.
Não tem como sugerir outro layout e um filtro pra restringir o número de registros retornados?

Como disse o amigo acima, não tem cristão que leia tantos registros assim.
E pense em outra coisa, 1669 páginas é como colocar 3 livros grossos em cima da mesa de alguém esperando que ele leia (isso pra UMA consulta).
Alguém realmente faz isso? Acredito que não né.

Acho melhor sugerir filtros pra restringir essa consulta, isso por si só deixará o relatório mais rápido por ter de trabalhar com bem menos registros.

blackout

AnjoVingador:
Giulliano:
na boa…NINGUÉM lê um relatório de 1.000+ páginas com trocentas colunas.

Eu sei que ninguém lê, mas tem que ser gerado, mesmo que não seja todo lido, mas alguém pode querer uma página lá no meio ou no final.
Ta bom eu exagerei nas colunas, são 10 no máximo, mas o número de páginas é 1669 mesmo.
Você tem alguma sugestão?

Outra coisa, mesmo que o cara precise de um registro lá no meio, ele poderia restringir a consulta inclusive pra achar o que ele precisa mais rapidamente.
Outra coisa que vc pode fazer, é tirar a consulta do relatório (apenas pra teste), e testá-la direto no banco de dados. Daí veja quanto tempo a consulta por si só leva pra te retornar todos esses registros. Quem sabe seja uma questão de performance da query.

Mas ainda assim, penso que o melhor é restringir a consulta pra retornar menos registros.

leoramos

Galera, não sei se é o caso, mas às vezes existem obrigações legais para esses relatórios.
Sugestões:

  • tu tens variáveis pra calcular algum campo? Se tiver, pense na possibilidade de fazer isso diretamente no SQL, fica mais rápido;
  • se são muitos cálculos, crie uma view;
  • agrupamento: se tiver algum agrupamento feito usando String, verifique se há um campo “<? extends Numeric>” que tu possas usar pro agrupamento, também ajuda;
  • indexe os campos que são usados pra ordenar / agrupar no teu BD;

Relatórios montados com beans geralmente são mais lentos que os SQL. Acho que teu padrão tá bom, mas confere essas coisas que te passei aí que já é uma força.

Abraço!

lucas_carvalho100

Não quero discordar da galera aqui, pois não sei o tipo do relatório e existem alguns relatórios contábeis que precisa ser retirados, mesmo para serem arquivados, não sei se esse é o caso…
Enfim acho que você deveria postar, a query para tentarmos ajudar você, se for esse o caso, caso não seja algo contábil, aconselho a você a restringir a busca (seguindo o conselho inicial de todos)… Porque 1600 páginas é coisa pra caramba, vai demorar mesmo…

blackout

leoramos:
Galera, não sei se é o caso, mas às vezes existem obrigações legais para esses relatórios.
Sugestões:

  • tu tens variáveis pra calcular algum campo? Se tiver, pense na possibilidade de fazer isso diretamente no SQL, fica mais rápido;
  • se são muitos cálculos, crie uma view;
  • agrupamento: se tiver algum agrupamento feito usando String, verifique se há um campo “<? extends Numeric>” que tu possas usar pro agrupamento, também ajuda;
  • indexe os campos que são usados pra ordenar / agrupar no teu BD;

Relatórios montados com beans geralmente são mais lentos que os SQL. Acho que teu padrão tá bom, mas confere essas coisas que te passei aí que já é uma força.

Abraço!

Obrigações legais? Mas não estoudizendo pra retirar esse ou aquele campo, estou falando pra restringir o número de registros. O resultado final é o mesmo relatório, os mesmos campos, só que com menos registros, facilita a visualização inclusive.

De qualquer modo, suas dicas pra melhorar o desempenho são validas sim.

leoramos

Eu lido com relatórios contábeis; pensei d’ele ter as mesmas restrições que eu. Livro Diário ou Razão, por exemplo, não tem jeito: sou obrigado a emitir o relatório inteiro, sem filtros, uma vez por mês. Foi mais nesse sentido.
Mas claro, se ele puder filtrar, melhor ainda! Menos é mais, nesse caso hehe

AnjoVingador

blackout:
AnjoVingador:
Giulliano:
na boa…NINGUÉM lê um relatório de 1.000+ páginas com trocentas colunas.

Eu sei que ninguém lê, mas tem que ser gerado, mesmo que não seja todo lido, mas alguém pode querer uma página lá no meio ou no final.
Ta bom eu exagerei nas colunas, são 10 no máximo, mas o número de páginas é 1669 mesmo.
Você tem alguma sugestão?

Outra coisa, mesmo que o cara precise de um registro lá no meio, ele poderia restringir a consulta inclusive pra achar o que ele precisa mais rapidamente.
Outra coisa que vc pode fazer, é tirar a consulta do relatório (apenas pra teste), e testá-la direto no banco de dados. Daí veja quanto tempo a consulta por si só leva pra te retornar todos esses registros. Quem sabe seja uma questão de performance da query.

Mas ainda assim, penso que o melhor é restringir a consulta pra retornar menos registros.


A sim desculpe pessoal, os filtros existem sim essas 1669 páginas correspondem a gerar sem filtros, mas o cliente está avaliando em cima destas 1669 páginas.
As querys já estão otimizadas.
Será que mudar para objeto dá jeito?

Sim são relatórios contábeis, para prefeituras então são muitos dados e alguns cálculos envolvidos.

leoramos

Não, cara… vais piorar teu problema, na minha opinião.
Chegasse a ver o que postei antes?

lucas_carvalho100

Posta a query…

AnjoVingador

leoramos:
Galera, não sei se é o caso, mas às vezes existem obrigações legais para esses relatórios.
Sugestões:

  • tu tens variáveis pra calcular algum campo? Se tiver, pense na possibilidade de fazer isso diretamente no SQL, fica mais rápido;
  • se são muitos cálculos, crie uma view;
  • agrupamento: se tiver algum agrupamento feito usando String, verifique se há um campo “<? extends Numeric>” que tu possas usar pro agrupamento, também ajuda;
  • indexe os campos que são usados pra ordenar / agrupar no teu BD;

Relatórios montados com beans geralmente são mais lentos que os SQL. Acho que teu padrão tá bom, mas confere essas coisas que te passei aí que já é uma força.

Abraço!


1-Mas se eu calcular direto no sql não irei ficar preso a um banco específico não?
2-Como seria criação da view.
3-Vou verificar.
4-Já foi feito.

Relátorios usando beans são mais lentos que o relatório executando uma 11 querys diferentes?
Eu não cheguei testar relatórios grandes por objetos.
É mais lento mesmo?

leoramos
1- Dependendo do cálculo, não. Mas se tu   usando SQL puro, se bobear   preso;

2- Cria uma view com base no teu select calculado;  uma fuçada no google em como criar views no teu tipo de banco;

Não tenho um benchmark aqui pra dizer que é mais lento ou não, mas considerando que vais passar por um processo a mais (conversão dos dados pros Beans), eu acredito que fique, sim, mais lento.

Abraço!
AnjoVingador

Pessoal só pra ficar registrado, fiz o teste com relatório usando objeto, seguindo um tutorial aqui do GUJ (o nome do arquivo que baixai é Ireporttutorial.rar).
Eu adicionei o hibernate para buscar os dados no banco pra mim.
O resultado foi muito bom, levou a metade do tempo fazendo com objeto em relação a passando a conexão do BD pro relatório.
Me supreendi com o resultado.
Relatório de mais de 3000 páginas gerou mais rádido que relatório de 1600 páginas.

É isso aí pessoal.

leoramos

Tá aí algo que me deixou surpreso. Em geral, o relatório com SQL é mais rápido.
Sem querer “chutar” explicação, mas já chutando: acho que ao fazer com Hibernate, a modelagem do dados do teu relatório ficou melhor. Fora questão de cache, que também pode ter ajudado.
Sempre bom lembrar que não há verdade absoluta… cada problema com a sua solução.
Legal, cara.
Abraço!

AnjoVingador

leoramos:
Tá aí algo que me deixou surpreso. Em geral, o relatório com SQL é mais rápido.
Sem querer “chutar” explicação, mas já chutando: acho que ao fazer com Hibernate, a modelagem do dados do teu relatório ficou melhor. Fora questão de cache, que também pode ter ajudado.
Sempre bom lembrar que não há verdade absoluta… cada problema com a sua solução.
Legal, cara.
Abraço!

De repente não estamos fazendo aqui da melhor forma com SQL.
Mas me incomodava muito o software usando o hibernate e passando a conexão para o relatório montar os dados, ainda mais pelo banco de dados ser em outra máquina.
E eu não sei bem como o relatório faz uso desta conexão.

Mas valeu pela ajuda.

A

Não sei muito de Jasper Reports, mas já consegui fazer uma query levar de 26 segundos para 200 milissegundos, utilizando simples conceitos de bancos de dados e JDBC.

Primeira coisa que é bom lembrar, é que bancos de dados fazem "planos de acesso" quando se vai acessar alguma informação. Se sua query é muito complexa, o banco de dados vai levar um tempão para descobrir o plano de ataque para responder essa query. Para evitar isso, os bancos costumam suportar queries parametrizadas: ele calcula o plano uma única vez, e nas próximas vezes utiliza o mesmo plano para queries diferentes, nas quais só o parâmetro é utilizado.

Por exemplo: seja o query "SELECT nome, endereco, telefone WHERE nome > 'ANA' and endereco like '%belovese'";

Se eu chamar esse query como

Statement stmt; 
.
.
.
stmt.executeQuery("SELECT nome, endereco, telefone WHERE nome > 'ANA' and endereco like '%belovese'");
O banco de dados vai: -achar o plano de ataque para recuperar essa informação. -executar o plano para obter os resultados; E quando você chamar
stmt.executeQuery("SELECT nome, endereco, telefone WHERE nome > 'BELARMINA' and endereco like '%cetomina'");
Adivinha o que o banco vai fazer? A mesmíssima coisa, porque o intelejumento do banco de dados vai entender que essas consultas são diferentes. Como posso corrigir isso? Usando um preparedStatement.
PreparedStatement ptmt; 
.
.
.
ptmt.prepareStatement("SELECT nome, endereco, telefone WHERE nome > ? and endereco like ?");
ptmt.setString(1,"ANA");
ptmt.setString(2,"%belovese");
ptmt.executeQuery();

.
.
.
ptmt.prepareStatement("SELECT nome, endereco, telefone WHERE nome > ? and endereco like ?");
ptmt.setString(1,"BELARMINA");
ptmt.setString(2,"%cetomina");
ptmt.executeQuery();

O que muda dessa vez? O plano é preparado com base em variáveis. Na segunda chamada ao query (e, notem, isso vale para qualquer consulta parametrizada que você fizer, não importa a sessão da máquina virtual ou qual JVM você está utilizando, porque o plano fica no banco de dados...), o banco de dados já vai ter gravado o "plano de ataque" e atuar concordantemente.

Moral da história:

Evitem *ao máximo* montar sql dinamicamente. Sempre tente fazer os queries parametrizados.

Espero que isso ajude...

AnjoVingador
abmpicoli:
Não sei muito de Jasper Reports, mas já consegui fazer uma query levar de 26 segundos para 200 milissegundos, utilizando simples conceitos de bancos de dados e JDBC.

Primeira coisa que é bom lembrar, é que bancos de dados fazem "planos de acesso" quando se vai acessar alguma informação. Se sua query é muito complexa, o banco de dados vai levar um tempão para descobrir o plano de ataque para responder essa query. Para evitar isso, os bancos costumam suportar queries parametrizadas: ele calcula o plano uma única vez, e nas próximas vezes utiliza o mesmo plano para queries diferentes, nas quais só o parâmetro é utilizado.

Por exemplo: seja o query "SELECT nome, endereco, telefone WHERE nome > 'ANA' and endereco like '%belovese'";

Se eu chamar esse query como

Statement stmt; 
.
.
.
stmt.executeQuery("SELECT nome, endereco, telefone WHERE nome > 'ANA' and endereco like '%belovese'");
O banco de dados vai: -achar o plano de ataque para recuperar essa informação. -executar o plano para obter os resultados; E quando você chamar
stmt.executeQuery("SELECT nome, endereco, telefone WHERE nome > 'BELARMINA' and endereco like '%cetomina'");
Adivinha o que o banco vai fazer? A mesmíssima coisa, porque o intelejumento do banco de dados vai entender que essas consultas são diferentes. Como posso corrigir isso? Usando um preparedStatement.
PreparedStatement ptmt; 
.
.
.
ptmt.prepareStatement("SELECT nome, endereco, telefone WHERE nome > ? and endereco like ?");
ptmt.setString(1,"ANA");
ptmt.setString(2,"%belovese");
ptmt.executeQuery();

.
.
.
ptmt.prepareStatement("SELECT nome, endereco, telefone WHERE nome > ? and endereco like ?");
ptmt.setString(1,"BELARMINA");
ptmt.setString(2,"%cetomina");
ptmt.executeQuery();

O que muda dessa vez? O plano é preparado com base em variáveis. Na segunda chamada ao query (e, notem, isso vale para qualquer consulta parametrizada que você fizer, não importa a sessão da máquina virtual ou qual JVM você está utilizando, porque o plano fica no banco de dados...), o banco de dados já vai ter gravado o "plano de ataque" e atuar concordantemente.

Moral da história:

Evitem *ao máximo* montar sql dinamicamente. Sempre tente fazer os queries parametrizados.

Espero que isso ajude...

Cara muito boa sua informação, realmente não tinha conhecimento deste funcionamento.
Vou lembrar disso quando eu usar JDBC para fazer coisas simples.
Valeu mesmo.
Em relação ao jasper eu acho que o problema não está nas querys e sim como ele faz uso da conexão que lhe é passada.
As querys quando executadas separadamente são executadas até bem rápidas.

Criado 18 de julho de 2011
Ultima resposta 27 de jul. de 2011
Respostas 18
Participantes 6