terça-feira, 9 de fevereiro de 2010

O conto do merge, persist e do No Transaction

2

Era uma vez...

Ehehhe, brincadeiras a parte, esses tempos tive um pequeno problema com uma certa demora usando JPA em um modulo EJB.

Tive de fazer a rotina de leitura de um arquivo texto e importar os registros para o sistema. até ai sem problemas, fiz a rotina e ela rodava em menos de 5s e importava todos os registros. Porém os registros que vinham no arquivo não atendiam a modelagem do sistema, ou seja, teria que inserir nas outras tabelas caso não existisse.

feita as Querys para encontrar o registro, e caso não existisse criar um novo, do nada ele demorou aproximadamento 6hrs e ao final la pela 1h30min da manhã uma execessão de No Transaction Active foi lançada em um flush no Entity Manager.

Lá fui eu aplicar algums caches de memoria para diminuir as consultas ao banco e os salvamentos. resolvemos mudar alguns merges para persist pois seguindo o que o pessoal fala, o persist é somente para objetos novos e é muito mais rapido.

Pois é não foi. Os objetos usando persist se tornaram pesados, e o procedimento ficou pesado, interrompido em 30min de execução tendo percorrido somente 200 registros (o arquivo possuia 30k). Removi o persist e deixei tudo como merge, mais uma vez uma No Transaction lá pelo registro 3mil é lançada. mais por que existe transação até o 2999. Eis que me dizem, põe um clear no começo do loop.

Galera, nunca vi o treco ir tão rápido ehhehe. Todo o gargalo de processamento se foi e o procedimento rodou em 5min.

Pra quem já teve esse problema não esqueça, o clear é muito importante :)

Aproveitando que estou falando sobre JPA e EJB...
Estavamos também com um problema ao salvar (merge) alguns objetos, a performance muito baixa, levava quase 2min para salvar o objeto, isso pos a chamada do em.merge.

Fiz varios testes, inclusive usando o clear, porém não deu em nada, resolvi arriscar, o problema estava nos objetos que eram atualizados e vinham do cliente, ou seja, estavam foram do contexto do EJB e do entity manager. Não sei se isso é gambiarra ou não, mas a performance melhorou drasticamente caindo para 2s.


  • primeiro passo eu recupero o objeto usando o em.find.

  • depois atribuo a esse objeto recuperado o objeto passado como parametro

  • dai só fazer o merge



Simples e pratico não :)

Espero que isso seja de ajuda para mais alguém. Até a próxima

2 comentários:

Anônimo disse...

Eu já teria utilizado a interface nativa do Entity Manager para fazer isto dentro de uma transacao... iria poupar milhares de selects.

Rafael Felix disse...

Nos utilizamos um pool e quem gerencia a transação é o proprio conteiner, não precisamos nos preocupar com isso. Porém em determinado momento o EJB termina talvez por uma sobrecarga sobre o EntityManager, e o clear facilita muito isso.

 
Design by ThemeShift | Bloggerized by Lasantha - Free Blogger Templates | Best Web Hosting