Processamento (leitura, processamento e persistência) de grandes volumes de dados

Pessoal,

Preciso de opiniões para uma arquitetura: tenho que processar grandes arquivos em Java, que podem chegar a gigas. Cada arquivo precisa ser lido, processado (pode ser considerado pequeno) e persistido.

Um arquivo de 250M bytes resulta mais de 1 milhão de registros no banco.

Qual a forma mais eficiente para persistir os dados no banco?

Penso que seria uma carga via loader, contudo essa solução torna-se difícil pelo fato do processamento (leitura, processamento e persistência) de cada arquivo ser realizado multthread.

Sugestões???

Desde já agradeço. Obrigado

Se possível, converta os arquivos de entrada para outros que sejam fáceis de carregar no banco.

entanglement,

O problema é persistir os dados no banco. Mesmo que seja gerado um formato mais “fácil”, ainda é necessário abri-lo e colocar um volume significativo de registros no BD. O gargalo do processo é escrever milhões de registros no banco.

Assim, qual é a melhor alternativa para persistir grandes volumes de dados utilizando Java?

Abraços,

Boa dia

Aqui na empresa onde trabalho, desenvolvemos uma aplicação onde também a base de dados é alimentada através de arquivos bem grandes e de diferentes formatos, como nossa aplicação é uma web seria inviavél realizar tal tarefa através de upload ou coisas do tipo, então desenvolvemos uma rotina que roda no servidor interno da empresa que é responsavel por converter os arquivos em um formato intermediário e depois esses dados já processados são transmitidos para o banco de dados do servidor web.

Na parte de persistência utilizamos Hibernate/JPA em ambos os softwares, modelados para não ter problemas com estouro de memória e coisas do tipo pois são realizados diversos inserts e updates nesse processamento.

Falou.

Em primeiro lugar, não tente bufferizar o conteúdo desse arquivo. Isso resultaria num uso excessivo de memória. Use um Scanner p/ parsea-lo. A unica maneira portável de se fazer isso é através de um Connector.

Com relação ao tempo de processamento da tarefa, use uma Thread p/ cada arquivo p/ evitar de bloquear o sistema. Com EJB 3.1 vc pode usar a anotação @Asynchronous p/ fazer isso. E tente manter alguma informação p/ q o seu usuário saiba o q está acontecendo no sistema, tipo uma barra de progresso.

Caio,

Hibernate/JPA seria uma solução adequada para grandes volumes de dados? Será que insert via prepareStatmente não teriam um resultado melhor?

[]s

Não existem bulk inserts em JPA. Essa solução só é válida p/ deletes e updates. Q não é o caso.

Caros,

Via prepareStatmente pode se inserir um conjunto de inserts.

[]s

Sim, view PreparedStatement do JDBC. O JPA não possui funcionalidade semelhante. E mesmo o PreparedStatement não é uma boa solução pois isso o obrigaria a carregar todos os dados do arquivo na memória de uma só vez. Se os arquivos são tão grandes como ele diz isso seria um terrível overhead de memória.

dev.rafael,

Posso ler o arquivo aos poucos e persistir, esse não séria um problema. A principal dificuldade é encontrar um mecanismo eficiente para persistir dos dados no BD. Note que posso, tenho condições, de aplicar diretamente instruções de insert.

A questão é qual a melhor forma de persistir dados? o que é mais eficiente.

[]s

Ler o arquivo em partes e manter uma segunda Thread lendo novas partes do arquivo enquanto as queries são executadas deve, provavelmente, ser a solução q oferece mais performance. Mas se esse é um processo muito longo e q, de qualquer forma, deve tomar vários minutos/horas p/ ser executado não vejo uma boa razão p/ uma solução tão complicada. Os objetos um a um do arquivo e usar o JPA deve ser uma solução mais simples, menos suscetível a bugs e mais fácil de testar q e manter q o usar JDBC. Com JPA em mãos, JDBC é um recurso q eu só recorro em casos extremos quando não posso atingir os requisitos da com o JPA (ou quando, em raros casos, o JPA produz soluções ainda mais complicadas q JDBC). Prezar por um código simples é sempre uma boa idéia, pois isso reduz bugs e melhora a mantenibilidade além da produtividade. As vezes vale a pena fazer pequenos sacrifícios de performance p/ conseguir um código mais simples. Pequenos! Como eu disse, se isso vai demorar p/ executar de qualquer forma pq não manter um código simples?

Também prezo pela qualidade do código.
Alguma outra opinião?

[]s

Boa tarde

Então como falaram acima em aplicações desse tipo temos que tomar cuidado com overhead de memória, nos aqui optamos por utilizar JPA com Spring devido as diversas regras de negocio e transações que nessa rotina são realizadas, com relação a performance não perdemos nada, pelo contrário, a aplicação esta funcionando perfeitamente e esta bem rápida, nossa aplicação aqui é multi-thread, onde cada processo que aplicação executa são separadas em thread diferentes.

Falou.

Desculpe mas não há como dizer q um framework q converte queries JPAQL em SQL e depois converte ResultSets em listas de objetos não tem nenhum impacto negativo na performance. Contudo esse impacto é pequeno o bastante p/ não ser notado em 99% dos casos, e a simplicidade oferecida por ele compensa.

Boa tarde

Como disseram acima, com certeza há uma diferença de performance entre JPA e JDBC devido aos parses que devem ser feitos internamente pelo framework, mas para ver realmente se esta diferença irá impactar no seu sistema, depende do tipo de aplicação e como ela foi modelada, como disse no nosso caso aqui, não notamos essa diferença, pois este modelo se adaptou perfeitamente no nosso domain, principalmente pelo fato de existirem diversas transações para os valores do arquivo.

Recomendo você antes de definir qual modelo irá utilizar, realizar alguns testes para ver qual se adapta melhor a sua necessidade.

Até mais.

Quando se tem milhões de registros e gigabytes de dados, a simplicidade é inevitavelmente posta de lado em prol da performance.
Na (aparente) situação descrita pelo marciano1, eu ficaria com medo de lidar com qualquer coisa diferente de JDBC.qualquer 1% faz a diferença.E enquanto estiver ocorrendo esse processamento, o uso da VM iria para o céu.
Espero que ele tenha um server dedicado só para essa tarefa.

Acho que mesmo assim, vai ser f… milhões de registros sempre dão trabalho.

marciano1, vc terá que fazer alguma(s) verificação(ções) enquanto esses dados são persistidos?(Saber se um ID já existe, não permitir nomes repetidos…espero que NÃO-overhead insustentável-, mas se tiver, crie uma tabela temporária só para jogar esses dados e depois faça as verificações devidas e grave na principal do seu sistema!)