OutOfMemory-Como Realizar Consultas Gigantes

29 respostas
V

Pessoal é o seguinte:

Estou Realizando uma consulta gigantesca em uma tabela do banco de dados,a qual possui 300.000 registros,estou passando este dados para objetos para depois grava-los em xml,só que quando quando esta realizando a consulta dá uma Exception:Java.Lang.OutOfMemory.

-Ja Otimizei minha JVm com os parametros -vmargs -Xms512M -Xmx1100M -XX: + AggressiveHeap que coloca toda a memoria disponivel para a JVM;

-Ja Executei o GarbageCollector em cada dado trazido do banco;

-Nao sei mas o q faço!! <img src="https://cdn.jsdelivr.net/gh/twitter/twemoji@14/assets/72x72/c.pngry.png?v=9" title=":cry:" class="emoji" alt=":cry:">

Alguma ideia de como melhor gerenciar a memoria,como limpar a memoria,alguem ja passou por isso? Lembrando que eu preciso desses objetos com as informaçoes para grava-los em XML…

Ideias,sugestoes,experiencias?! preciso muito disso…

29 Respostas

E

300000 registros em uma consulta? Para gerar um XML? Use JDBC puro e para gerar o XML, faça “no braço”. Número de objetos criados e consumo de memória: quase zero.
http://www.ibiblio.org/xml/books/xmljava/chapters/index.html

A

Reforçando um pouco o que o entanglement falou, acho que o importante é eliminar o intermediário. Se você faz uma consulta ao banco para depois gerar o XML, seria melhor que você não colocasse, mesmo, objetos no meio.

[]'s

R

@entanglement e @asaudate

concordo com a abordagem de vcs…

mas “paginar” essa consulta em digamos 10 mil registros, tb nao solucionaria o problema ? evitando ter de escrever o xml na mao e usar o jdbc…

/*edit */
alias, sera que ele nao esta mantendo referencia aos objetos?

Se td estivesse correto, ele faria busca do obj, parse pra xml, grava o arquivo e descarta os objs… entao o gc limpa e assim vai ?
/* /edit */

abrasss

V

Psssss…acredito q seria mt trabalho a primeira sugestao pelo fato de eu estar com pouco tempo para entregar o projeto,e paginar os resultados tbm nao me ajuda.
Eh axo q vou ter q mudar a implementaçao pois cada vez minhas alternativas e esperanças se acabam…estava pensando agora em vez de consultar os dados e criar objetos e grava-los em xml,nao daria para pegar esses dados e grava-los em uma banco embutido como o sqLite???Assim talvez evitaria o consumo de memoria e criaçao de objetos,tipo consultou na mesma hora ja inseriu no banco SQlite(Ou ate mesmo paginando os resultados e depois inserindo-os no SQLite),eliminaria os intermediarios…Eh q eu preciso transportar esses dados de qualquer maneira.

O q voces axam??eh Viavel??

V

Pois eh,desconfio que o Garbage Collector nao funciona tao bem assim,tentei tbm otimiza o codigo o maximo possivel,mas nao deu.
O problema que o Estouro de memoria ocorre antes msm de ele chegar a serializar os objetos em xml…:frowning:

V

Cara, uma outra possibilidade eh voce efetuar uma consulta parcial, por exemplo: primeiro recupere os primeiros 50% dos dados, depois os 50% restantes.

abrs

E

vvp0:
Psssss…acredito q seria mt trabalho a primeira sugestao pelo fato de eu estar com pouco tempo para entregar o projeto,e paginar os resultados tbm nao me ajuda.
Eh axo q vou ter q mudar a implementaçao pois cada vez minhas alternativas e esperanças se acabam…estava pensando agora em vez de consultar os dados e criar objetos e grava-los em xml,nao daria para pegar esses dados e grava-los em uma banco embutido como o sqLite???Assim talvez evitaria o consumo de memoria e criaçao de objetos,tipo consultou na mesma hora ja inseriu no banco SQlite(Ou ate mesmo paginando os resultados e depois inserindo-os no SQLite),eliminaria os intermediarios…Eh q eu preciso transportar esses dados de qualquer maneira.

O q voces axam??eh Viavel??

Muito complicado. Por que é que não faz do jeito bobo que lhe falei? É mais rápido e mais fácil.

V

Pois eh…eu poderia tentar,ia elimina o uso de objetos…e depois para ler poderia ler com o Xstream msm colocando um “Alias”…mas na hora de ler poderia estourar o buffer tbm pois o xml iria ficar gigante…e a organizaçao na seria das melhores…
Antes q me perguntem q loucura eu estou fazendo,estou desenvolvendo um transportador de dados de um banco para outro,ou seja pegar os dados de determinadas tabelas de um banco e passa-los para outro banco,por isso preciso de uma certa “Organizaçao”,pois nao sei qual tabela q vira,os selects sao feitos dinamicamente de acordo com a estrutura das tabelas…por isso pensei no SQLite…

R

amigao o gc funciona sim

e eh claro que vai dar estouro, pelo que vc escreveu acima vc esta buscando TODOS os objs da base de dados, pra dps parsear e gravar o arquivo.

caso não vá fazer como o entanglement explicou, o melhor é vc fazer o processo com uma consulta parcial e lembre-se de liberar os objs pro GC.

abrasss

E

Ah, agora entendi o que você quer. Você quer um “IMP” e “EXP” do Oracle mas “genérico”, mas usando JPA e XML (que são as piores escolhas nesse caso).

Exporte a consulta do banco para um simples arquivo CSV, e leia de volta esse CSV no outro banco. Melhor ainda, se puder, veja se a exportação pode gerar o formato que o outro banco espera para as ferramentas dele, isso irá fazer algo muito mais rápido.

V

Ah sim…claro claro eh uma ideia boa paginar e gravar os resultados,assim digamos para uma determindada tabela teria varios xml com os dados cada xml digamos com 5000 informaçoes…

E sobre o CSV…vou dar uma pesquisada ver o q é…E mando minhas conclusoes…

X

Só uma pergunta, por que gerar o XML? Existe um outro programa que “já está pronto” para isso ou você vai fazer um programa que importe esse xml para o outro banco?

V

Vou fazer um “Importador” que leia esses xmls e insere as informaçoes contidas nele nas respectivas tabelas do outro banco

E

Como eu disse, o pior formato para você transportar essa quantidade de dados é o XML (isso porque tem muita informação redundante), e o pior jeito para consultar essas tabelas é o JPA.

Se você quer simplesmente transportar tabelas de forma genérica, então use um formato bem bobo, como o CSV, e faça as consultas de um jeito bobo com JDBC mesmo. É muito mais simples, mais flexível - embora você esteja reinventando a roda, porque muitos bancos de dados (como o MS SQL Server, com o “DTS” - Data Transformation Services) têm utilitários para fazer esse transporte de tabelas entre um banco e outro.

E

Além disso, a inserção no outro banco normalmente não se faz só com Java, mas usando alguma ferramenta do banco destino que aceite um arquivo-texto (formatado de acordo com a necessidade da ferramenta) que permita inserir milhares ou milhões de linhas de uma vez só, como é o caso do IMP em antigas versões do Oracle.

B

caso seu banco seja oracle, vc pode facilmente fazer isso com as funcionalidades de xml que vem com o mesmo …

F

Eu já fiz isso e é tranquilo! Segue o algoritmo:

  • Faça paginação de acordo com tamanho da seu memoria limite da maquina. Quanto maior o HEAP da JVM, menores as paginas e mais rapido é a execução do processo.
  • Deixa todos os objetos gastos na paginação processada elegível para o GC limpar.
  • Reuse tudo, instanciando 1 vez os objetos compartilhados por todas as paginas.
  • Traga somente os campos necessários d instrução SQL.
  • Não use camada intermediarias com ORM, se atendo somente a JDBC.
X

E por que não fazer tudo em 1? O programa lê os dados e já insere no outro banco! Isso não é possivel? Por que a necesside de criar uma arquivo para essa importação exportação?
Já fiz a exportação de um banco em Sybase para Oracle usando só SQL, é 1000 vezes mais fácil e prático do que usar objetos!

X

Como eu disse, o pior formato para você transportar essa quantidade de dados é o XML (isso porque tem muita informação redundante), e o pior jeito para consultar essas tabelas é o JPA.

Se você quer simplesmente transportar tabelas de forma genérica, então use um formato bem bobo, como o CSV, e faça as consultas de um jeito bobo com JDBC mesmo. É muito mais simples, mais flexível - embora você esteja reinventando a roda, porque muitos bancos de dados (como o MS SQL Server, com o “DTS” - Data Transformation Services) têm utilitários para fazer esse transporte de tabelas entre um banco e outro.

Concordo com você. Usar JDBC e Arquivos Texto com separador, como CVS é muito mais fácil e simples do que utilizar ORM e XML e eu utilizaria o arquivo texto se e somente se fosse necessário, senão faria uma exportação direta dos dados de um banco para outro usando somente JDBC.

Sem querer ofender, mas qual o seu conhecimento de SQL e JDBC vvp0?

V

…Nao estou usando JPA,estou fazendo com JDBC mesmo,e tambem o XML para tabelas pequenas ate 15000 registros funciona perfeitamente…otimizei o meu codigo ao maximo,liberando os objetos depois de usados e chamando o GC,vou testar…se nao der Out.of.Memory deixarei esra primeira versao em XML mesmo,e iniciarei o desenvolvimento de 2 versao com o SQlite embutido,que armazenara as informaçoes…sem uso de objetos…consultou no banco ja inseriu na mesma hora no sqLite…alem das informaçoes ficarem melhor armazenadas e consistentes,pois trabalharei com tabelas gigantescas e com muitos relacionamentos…

Meu conhecimento em SQL é basico…select e insert soh…as verificaçoes faço tudo em java…

V

E por que não fazer tudo em 1? O programa lê os dados e já insere no outro banco! Isso não é possivel? Por que a necesside de criar uma arquivo para essa importação exportação?
Já fiz a exportação de um banco em Sybase para Oracle usando só SQL, é 1000 vezes mais fácil e prático do que usar objetos!

O problema é que os bancos estarão distantes,ou seja um em Sao Paulo e o outro em Porto Alegre…e essa ferramenta deve ser o mais simples possivel para poder ser manipulada por pessoas com pouco conhecimento…entao precisa de um meio para estes dados ficarem armazenados

V

eh…deu Out.of.Memory denovo mesmo com toda a otimizaçao do codigo,mas engraçado estourou a exception com o Javaw.exe ocupando apenas 102,224 K no gerenciador de tarefas,e mais a minha JVM esta configurada para Agressive Heap…

F

O windows realmente não libera o tanto de memoria configurado para JVM kkkkk…
Diminua o tamanho da paginação…

V

O windows realmente não libera o tanto de memoria configurado para JVM kkkkk…
Diminua o tamanho da paginação…

Pssssss…q @!!$#@# esse Windows…bem q eu desconfiava q as configuaraçoes da JVM nao tinha sido aplicadas…terei que fazer uma verificaçao no numero de registros,para se forem muitos realizar a paginaçao,senao nao,assim reduz o numero de xms desnecessarios.

F

O windows realmente não libera o tanto de memoria configurado para JVM kkkkk…
Diminua o tamanho da paginação…

Pssssss…q @!!$#@# esse Windows…bem q eu desconfiava q as configuaraçoes da JVM nao tinha sido aplicadas…terei que fazer uma verificaçao no numero de registros,para se forem muitos realizar a paginaçao,senao nao,assim reduz o numero de xms desnecessarios.

Sim…faça um código dinâmico ai que faça a paginação no seu resultset…

X

Qual o banco de dados que você esta usando? Os dois são iguais?

V

Oracle,os dois tem exatamente o mesmo schema.

X

Cara, acho que você esta indo pelo caminho errado. Existem ferramentas do banco que fazem isso de maneira automática. Nunca fiz isso no Oracle, mas no MySQL você pode replicar os dados de um banco Master para um Slave (http://dev.mysql.com/doc/refman/4.1/pt/replication.html)
Eu dei uma pesquisada rápida no google pela palavras “replicação oracle” e achei essa matéria da devmedia:http://www.devmedia.com.br/articles/viewcomp.asp?comp=9371
Tem outros diversos links a esse respeito.
Uma das vantagens da replicação é que são atualizados somente os registros que forem alterados e não toda a base de dados.

Acho que essa é a melhor opção para você…

V

Cara, acho que você esta indo pelo caminho errado. Existem ferramentas do banco que fazem isso de maneira automática. Nunca fiz isso no Oracle, mas no MySQL você pode replicar os dados de um banco Master para um Slave (http://dev.mysql.com/doc/refman/4.1/pt/replication.html)
Eu dei uma pesquisada rápida no google pela palavras “replicação oracle” e achei essa matéria da devmedia:http://www.devmedia.com.br/articles/viewcomp.asp?comp=9371
Tem outros diversos links a esse respeito.
Uma das vantagens da replicação é que são atualizados somente os registros que forem alterados e não toda a base de dados.

Acho que essa é a melhor opção para você…

Pois eh cara,existem varias soluçoes legais e eficientes para a transferencia de dados,mas eu preciso desenvolver essa ferramenta…mas vlw a todos pelas dicas!!Me deram bastante ideias para seguir em frente! :smiley:

Criado 5 de setembro de 2011
Ultima resposta 11 de set. de 2011
Respostas 29
Participantes 8