Olá…
Tenho um servidor Linux com ip válido e estou fazendo testes de sistemas (swing) conectando num banco PostgreSQL que está nesse servidor…
Ou seja… estou conectando no banco pela WAN e não pela LAN…
O sistema está paginado, evitando criação de objetos desnecessários. O tráfego das telas (com selects, updates, inserts no banco) é rápida (claro… dependendo da velocidade da internet).
Só q o problema é na hora de gerar um relatório… se o usuário quiser um relatório de TODOS os clientes ele vai tirar um e a demora será enorme se o banco tiver uns 2000 clientes por exemplo…
como faço pra resolver este problema? existe alguma forma de eu carregar todos os clientes sem demorar tanto?
As views, neste caso, resolveriam o problema de desempenho?
obs.: a paginação foi feita com limit e offset na sql mas no relatório eu não posso paginar pois devo exibir todos os registros…
Desempenho do PostgreSQL
21 Respostas
Use uma VPN que compacte os dados enviados via Internet entre o servidor e o cliente.
mesmo que o sistema for swing e não web?
e eu posso fazer tranquilamente este acesso ao banco direto?
Primeiro verifique onde está o gargalo.
pode estar no banco postgresql, pode estar na rede ou pode estar no sistema swing.
Depois disso, ataque o problema, se for no banco tente melhorar a query ou paralelizar a geração da massa de dados, etc.
o problema é somente na hora de gerar um relatório…
digamos… um “select * from clientes” listando numa JTable é rápido porém tirar um relatório com “select * from clientes” é muito demorado…
então o problema é no código que gera o relatório.
Dá uma estudada nesse código para saber em que ponto está consumindo mais processamento.
O netbeans tem um profiler que ajuda nessa tarefa.
try {
PreparedStatement ppst = new SQLManager().getPreparedStatement(sql);
ResultSet rs = ppst.executeQuery();
JRResultSetDataSource jrrs = new JRResultSetDataSource(rs);
HashMap parametros = new HashMap();
parametros.put("FOTO_EMPRESA", getLogoEmpresa());
JasperPrint jprint = JasperFillManager.fillReport(
url, parametros, jrrs);
JasperViewer jv = new JasperViewer(jprint, false);
jv.setVisible(true);
jv.setTitle(titulo);
jv.setExtendedState(jv.MAXIMIZED_BOTH);
jv.setDefaultCloseOperation(jv.DISPOSE_ON_CLOSE);
}catch (Exception e){
e.printStackTrace();
}
select * from empresas, clientes where ativa='S' order by nomecliente
chamo na sql a tabela empresas tb pois monto o cabeçalho com a logomarca e o nome da empresa do usuário..
Qual é o tamanho do JPG da logomarca da empresa?
Repete várias vezes?
a foto não é o problema pois na tabela veiculos carrego 5 fotos ao mesmo tempo e mostro na tela e é rápido…
e o processo de gravação da imagem no banco tb compacta a imagem e depois grava…
e não está repetindo várias vezes pois o campo ativa é da tabela de empresas e só é permitido uma empresa ativa por vez… ou seja… só traz uma empresa do banco…
o estranho é q é só na hora de gerar o relatório…
tenho tabelas onde retirei a paginação e fiz o teste e puxou uns 1000 registros do servidor em menos de 4 segundos… agora quando gero um relatório desses mesmos dados a demora é enorme…
Então o problema é complexo, você vai ter que sentar na frente de um profiler e ver onde o bicho pega.
Não tem jeito de saber sem ver o código rodando
estranho… fiz outro teste agora puxando gerando um relatório com 11 registros apenas e demorou uns 15 segundos…
lembrando q essa demora é só na hora de gerar um relatório e a sql é praticamente a mesma para listar numa JTable e no relatório…
quando eu conecto com o banco local eu tiro um relatório e a demora é imperceptível…
resumindo…
tráfego de dados nas telas: Local - Rápido, Servidor: Rápido (sendo q pelo servidor obviamente é um pouco mais demorado… mas questão de 1 segundo)
relatórios: Local - Rápido, Servidor: Extremamente demorado… mesmo quando o fluxo de dados é pequeno…
distribuindo a aplicação via WebStart não adiantaria?
descobri onde está o problema mas não sei como resolvê-lo…
é na sql na hora de pegar os dados da empresa… de alguma forma estes dados estão repetindo, o que obviamente não é o correto… preciso que os dados não repitam na sql (já tentei com uma sql dentro da sql mas a demora continua)
como faço pra pegar os dados da empresa necessários para o cabeçalho do relatório (nome foto e cidade) e DEPOIS pegar os dados do corpo do relatório?
tenho como fazer isso na mesma sql sem que os dados da empresa repitam para cada registro?
esta é a sql que NÃO demora:
select caixas.idcaixas, caixas.data, caixas.historico, caixas.entrada, caixas.saida, planodecontas.descricao from caixas, planodecontas where planodecontas.idplanodecontas = caixas.caixas_idplanodecontas and date_part('month', data)=? and date_part('year', data)=? order by data
e esta é a que demora:
Cara, coloca a estrutura de empresas, caixas e planodecontas pra eu poder te ajudar…
Cara, não tem como transformar essas sub-queries em outer joins???
Ou inner joins mesmo, dependendo da sua regra de negócio…
oi
um tempo atras eu achei este artigo, não cheguei a ler mas talvez possa te ajudar
eu ainda não implementei mas vou resolver o problema da seguinte maneira:
Antes de gerar o relatório eu pego a empresa que está ativa e passo os dados através de parâmetros no relatório…
assim eu posso tirar a empresa dos SQLs…
quando eu implementar eu posto o código…
obrigado a todos…
Cara não li todas as postagens mas reparei um problema muito comum no teu SQL.
Quando você utiliza dados de 2 ou mais tabelas você deve ter um campo de referência que liga os dados entre as 2 tabelas e indicar isso no comando SQL caso contrário a query se torna muito lenta mesmo.
No teu caso
select * from empresas, clientes where ativa=‘S’ order by nomecliente
digamos que a tabela empresas tenha o campo de valor único chamado de empresa_id, e na tabela clientes você tenha o campo que indica de qual empresa este cliente pertence chamado de empresa
a sua SQL ficaria assim.
select * from empresas E, clientes C where C.empresa = E.empresa_id AND ativa=‘S’ order by nomecliente
Não sei se falei besteira para você pois não sei qual a estrutura da sua base mas tive problema idêntico ao seu e foi facilmente resolvido indicando a relação entre as tabelas no comando SQL assim como indiquei acima…
Outra coisa que deixa muito lenta as querys é a mania ou preguisa de indicar os campos a usar, pra que carregar dados desnecessários utilizando SELECT *?
Para você ter uma idéia tenho uma base de dados com ~5.000.000 de registros e 22 campos a maioria varchar.
Ao fazer um SELECT * que me retorna 1.000 registros tenho o tempo de 36742ms
Ao fazer um SELECT campo1, campo6, campo7, campo8, … (15 campos) os mesmos 1.000 registros são retornados em apenas 8367ms
Abraços…
eu sei… mas neste caso não era vinculado…
mas isso já faz tempo… ja resolvi o problema… passei os dados da empresa via parâmetro pro relatório aí tirei a empresa da sql…