Bom tarde pessoal!
Estou precisando criar um txt, com resultados vindo de um resultset.
A consulta no banco, traz em torno de 10 milhoes de registros. Estou precisando inserir com uma performance melhor, pois está demorando muito.
Voces possuem alguma ideia, de como posso fazer para inserir todos esses registros mais rapido?
Segue codigo:
try{
Class.forName("org.postgresql.Driver");
Connection con= DriverManager.getConnection("jdbc:postgresql://IP:5432/banco","user","pass");
st = con.createStatement();
ResultSet rs = st.executeQuery(
"SQL");
File file = new File("arquivo.txt");
PrintWriter pw = new PrintWriter(file);
while(rs.next()){
pw.printf("rs.....");
st2 = con.createStatement();
ResultSet rs2 = st2.executeQuery("SQL2")); //Passo um rs.getString("lote") no parametro da segunda consulta
while(rs2.next()) {
pw.printf("rs2...");
}
}
pw.flush();
pw.close();
}catch(SQLException e){
e.printStackTrace();
}
}
Obrigado pela ajuda
Você poderia ir guardando os resultados em memória, até atingir um limite e aí faria o dump em disco, exemplo:
Class.forName("org.postgresql.Driver");
Connection con = DriverManager.getConnection("jdbc:postgresql://IP:5432/banco", "user", "pass");
Statement st = con.createStatement();
ResultSet rs = st.executeQuery("SQL");
File file = new File("arquivo.txt");
PrintWriter pw = new PrintWriter(file);
int count = 0;
int limite = 1000; // por exemplo gravar em arquivo somente a cada 1000 registros
StringBuilder memoria = new StringBuilder();
while (rs.next()) {
memoria.append("rs…");
if (++count > limite) {
count = 0;
pw.print(memoria.toString());
memoria = new StringBuilder();
}
Statement st2 = con.createStatement();
ResultSet rs2 = st2.executeQuery("SQL2"); // Passo um rs.getString("lote") no parametro da segunda consulta
while (rs2.next()) {
memoria.append("rs2…");
if (++count > limite) {
count = 0;
pw.print(memoria.toString());
memoria = new StringBuilder();
}
}
}
if (memoria.length() > 0) {
pw.print(memoria.toString());
}
pw.flush();
pw.close();
Mas eu acho uma má pratica você criar outros selects enquanto está iterando o ResultSet de um select anterior. Tente redesenhar suas duas queries em uma única pra trazer os resultados de uma só vez, aí você só tem um ResultSet pra iterar.
1 curtida
não da para resolver melhor em uma query com inner join … será que vc não esta fazendo muita coisa em um unico metodo ? se segmentar a responsabilidade não ficaria melhor?
outra forma é em vez de bater uma query no processamento do resultset (lazy load)
você poderia reservar os ids para a busca e bater no termino do processamento do result set uma query com os ids para a segunda busca.
Ai no processamento do retorno vc faz o merge na resposta final
O primeiro passo quando estiver enfrentando problemas de performance é medir o que está causando problemas.
No seu caso os suspeitos sao escrever no arquivo e queries para o banco de dados.
Fiz um teste aqui e consigo escrever 10 milhoes de linhas num arquivo em menos de 5 segundos.
Por outro lado, se cada query que você executa tomar 5ms (que é uma boa latência) e você está executando 10 milhoes de queries, seu processo vai levar quase 14 horas (se minha matemática tiver certa).
Como sugerido acima, melhor tentar transformar seus dois selects numa query única.
1 curtida
Também concordo, query única, sem complicações.
Dependendo do caso pode avaliar isso também: https://stackoverflow.com/questions/5331320/psql-save-results-of-command-to-a-file
Obrigado pessoal pela ajuda! Montei uma query unica e tambem estou gravando a cada 1000 registros. Esta bem melhor.
Obrigado a todos.