ResultSet gigante

7 respostas
J

Estou com um problema e queria ver se alguem poderia me indicar uma melhor solução:
Tenho que fazer um select enorme com varios joins e que retorna uma media de 30 à 50 mil registros e demora mais ou menos 1h e meia pra rodar o banco é Oracle 10g, em uma aplicação JWS, JDBC, WebSphere…

  • Solução temporaria foi criar uma outra tabela com o resultado do select tipo “CREATE TABLE tempTable AS SELECT…etc” e depois vou paginando esses dados de mil e mil e escrevendo um arquivo DBF que é a necessidade da aplicação, este processo esta demorando em média 2:15h para rodar, mas creio que ainda não é a melhor coisa criar essa tabela temporaria

  • Tentei usar assim só fazendo o select normal sem criar a tebala Statement stmt = dataSource.getConnection().createStatement(); stmt.setFetchSize(1000); ResultSet rs = stmt.executeQuery(query); mas esta demorando muitooooo mais… quase 10h então imagino que a cada mil ele esta execultando a query novamente no banco…

Tem, alguma forma de fazer isso ficar no proprio oracle, e eu trazer só de mil em mil no ResultSet e os dados ficar em cache no oracle e quando eu for ler o 1001 ele simplismente pegar no banco dessa forma ja posso ir direto escrevendo meu arquivo DBF sem Criar uma Tebala Temporaria, ganhar um OutOfMemoryError…

7 Respostas

Hebert_Coelho

Cara, ficar em cache do banco não sei.

Sei que o que vc poderia tentar fazer é “picotar” a consulta. Tenta utilizar o between.

SELECT * FROM CLIENTES WHERE ID = 123 //... BETWEEN valor1 AND valor2

Vc iria iterar sobre essa consulta e montar no seu cache. Colocaria tipo que de mil em mil. 1 … 1000, 1000 até 2000. Quando não tivesse mais resultado é pq acabou a consulta! ^^ Mas faça um intervalo que vc saiba que terá um resultado rápido, mas também não tão pequeno para não pesar seu servidor com requisições!

Crie uma lista no seu Java e armazena a moçada lá.

Q tal?

J

Acontece que a query em si demora muito… se eu ficar executando ela mesmo que por partes tem muitos joins e demora mais de 1h… queria executar uma vez e depois e lendo os dados por partes. Tem como?

claudiom

apesar de parecer um número grande, 50 mil registros para o oracle não é tanta coisa assim…

não sei com quantas tabelas essa query faz join, mas para demorar 1h:30min para rodar, eu desconfiaria que seu maior problema é a própria query…

considerando que a query toma 66% do tempo total de processo, talvez otimiza-la deveria ser sua primeira aposta.

E

No seu caso em particular, acho melhor deixar o resultado de sua query em uma tabela qualquer, para que outra aplicação possa manipular essa tabela menor (50000 registros é uma tabela minúscula) à vontade.

J

claudiom:
apesar de parecer um número grande, 50 mil registros para o oracle não é tanta coisa assim…

não sei com quantas tabelas essa query faz join, mas para demorar 1h:30min para rodar, eu desconfiaria que seu maior problema é a própria query…

considerando que a query toma 66% do tempo total de processo, talvez otimiza-la deveria ser sua primeira aposta.

Concordo. Mais não tem muito o que fazer na query… ja revi aqui com o DBA e não tem muito o que fazer, por que isse é todo o histórico da empresa de 2009… teoricamente isso só deve rodar uma vez por ano… e a previsão é que em 2011 quando for gerar de 2010 isso vá para 1milhão… por isso queria tentar otimizar o máximo… Há e a query tem 21 joins…

L

Opa… blz?
Cara eu revisaria essa query e indices dessas tabelas.
Ja tive problema com volume de informação mas não necessariamente de performance e utilizei limit na construção do sql (postgres) talvez isso possa te ajudar… espero que sim.

Abs

FacaNaCaveira

Fala ai jc.thalys

Uma das coisas que voce pode fazer é criar uma Stored Procedure no Oracle, pois após a primeira execução desta ela cria um plano de execução que é usado toda vez que ela é executada, isso economiza um tempo absurdo, toda vez que ela é executada. De repente pode ser uma boa alternativa e depois chama a procedure pelo JDBC (se for assim que vc esta usando)

import java.sql.*;

public class Dao {

    ResultSet rs;
    PreparedStatement stmt;
    Connection con;
    CallableStatement cs;

    public void open() throws Exception {
        Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
        con = DriverManager.getConnection("jdbc:sqlserver://bs501;databaseName=int_corretor_db", "root", "root");
    }

    public void close() throws Exception {
        con.close();
    }
}
import entity.*;
import java.util.*;

public class RelatorioDao extends Dao {

    public List<Relatorio> findAll(String dataInicial, String dataFinal) throws Exception {

        List<Relatorio> retorno = new ArrayList<Relatorio>();
        open();
        cs = con.prepareCall("cot_corretor_655_sps '" + dataInicial + "','" + dataFinal + "'");
        rs = cs.executeQuery();

        while (rs.next()) {
            Relatorio rel = new Relatorio();

            rel.setProduto(rs.getString("PRODUTO"));
            rel.setNomeProduto(rs.getString("NOME_PRODUTO"));
            rel.setRazaoSocial(rs.getString("RAZAO_SOCIAL"));
            rel.setCorretor(rs.getString("CORRETOR"));

            retorno.add(rel);
        }
        cs.close();
        close();

        return retorno;
    }

Aproveitei para colocar o codigo que usei para rodar uma SP no JDBC, pode ser util para o que vc quer fazer.

Abração 8)
Max

Criado 6 de agosto de 2010
Ultima resposta 13 de ago. de 2010
Respostas 7
Participantes 6