Desempenho do PostgreSQL

21 respostas
erico_kl

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…

21 Respostas

E

Use uma VPN que compacte os dados enviados via Internet entre o servidor e o cliente.

erico_kl

mesmo que o sistema for swing e não web?

erico_kl

e eu posso fazer tranquilamente este acesso ao banco direto?

furutani

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.

erico_kl

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…

furutani

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.

erico_kl
gero o relatório assim:
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();
		}
e a SQL é:
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..

furutani

Qual é o tamanho do JPG da logomarca da empresa?
Repete várias vezes?

erico_kl

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…

erico_kl

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…

furutani

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

erico_kl

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…

erico_kl

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…

erico_kl

distribuindo a aplicação via WebStart não adiantaria?

erico_kl

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:

kotho

Cara, coloca a estrutura de empresas, caixas e planodecontas pra eu poder te ajudar…

C

Cara, não tem como transformar essas sub-queries em outer joins???
Ou inner joins mesmo, dependendo da sua regra de negócio…

Andre_Fonseca

oi

um tempo atras eu achei este artigo, não cheguei a ler mas talvez possa te ajudar

Dicas de Performance em aplicações com PosgreSQL

erico_kl

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…

goofybnu

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…

erico_kl

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…

Criado 5 de outubro de 2009
Ultima resposta 2 de fev. de 2010
Respostas 21
Participantes 7