[quote=entanglement][quote=LeandroGM007]Galera,
Boa tarde.
Tenho uma aplicação que faz uma consulta numa base de dados Oracle que tem mais de 21 milhões de tuplas na tabela e tenho de memória disponível na JVM 4.0 GB. Porém, no trabalho quando o usuário tenta acessar a funcionalidade tentando realizar a consulta, ele não tem resposta e a aplicação cai por time out e, sempre no log da aplicação aponta o famoso problema de java.lang.OutOfMemoryError: Java heap space.
Alguém poderia me dar uma idéia de como faço para resolver esse problema?[/quote]
-
Filtre a consulta (para que serve o “where”?)
-
Use um ResultSet que seja “forward only”, e pegue os dados e os jogue em um arquivo à medida que você os vai lendo. Não guarde os dados em uma lista na memória senão alguma coisa vai estourar.
4 GB de memória parece muito mas quando você vai recuperar resultsets grandes você vai ver que isso é relativamente pouco.
Só para ter uma idéia, uma String com 20 caracteres ocupa mais ou menos 20 x 2 + 8 + 8 + 16 = 72 bytes, em vez dos 20 bytes que você espera.
E mesmo que você tenha 4GB no seu computador, se você estiver rodando uma JVM de 32 bits (que é normalmente o caso no Windows de 32 bits) você só tem disponível para o heap cerca de 1,5 GB.
[/quote]
++
Eu ainda insisto. Qual a necessidade você trazer em uma tela de busca, todos os 20.000 registro que você tanto fala ? Sendo que o usuário só vai ver uns 20 por página ?
Dependendo do tipo de dado que você estiver filtrando no seu WHERE, a consulta pode demorar mais, ou pode ser mais rápida, e sem contar que dependendo do banco, as avaliações de ordem das condições podem mudar (o que implica em tempo). Vou dar um exemplo no mysql bem básico:
1 - Pegue sua query, e faça um EXPLAIN suaQuery no banco e veja se é possível utilizar algum indice já existente, tente colocar na ordem dos wheres de acordo com seus indices.
2 - Use o LIMIT - esta é a regra mais importante!
3 - Se você tem uma quantidade de registros absurda, considere para fazer a paginação com a mesma consulta, POREM, trocando o select * FROM … por SELECT COUNT(1) AS registros FROM … ou SELECT COUNT(campo-de-maior-relevancia-q-seja-indice-q-nunca-vem-null) AS registros FROM …
3.1 - Aqui não adianta você querer fazer a paginação com um list.size() pois os registros já estão na memória e pode parecer que não, mas 10 usuários apertando o submit duas vezes aqui propositalmente, eles derrubam sua aplicação sem esforço algum.
3.2 - DEPENDENDO da forma como seu WHERE está feito, quase sempre é mais rápido para o banco de dados fazer um COUNT de 100.000 linhas, do que, separar 100.000 linhas para devolver para um processo, e, depois, o java ter que mapear essas 100.000 linhas na memória (Se tiver JPA/Hibernate aqui com lazy, é sentar para chorar
).
Trolltopic:
String has length+24 bytes of overhead over byte[]:
class String implements java.io.Serializable {
private char value[]; // 4 bytes + 12 bytes of array header
private int offset; // 4 bytes
private int count; // 4 bytes
}
fonte: http://www.jwz.org/doc/java.html 8)