Domanda

mi viene data un compito di convertire un enorme tavolo in un file XML personalizzato. Userò Java per questo lavoro.

Se ho semplicemente emissione di un "SELECT * FROM cliente", si può restituire enorme quantità di dati che alla fine causano OOM. Mi chiedo, c'è un modo che posso elaborare immediatamente una volta il record diventa disponibile, e rimuovere il record dalla memoria dopo che durante il processo di recupero di sql?

--- modificato il 13 Luglio 2009

Vorrei esporre la mia domanda. Ho 1 server db e 1 server applicazioni. Quando lancio una query di selezione in applicazione, i dati viaggeranno dal db server al server app.

Credo (correggetemi se sbaglio) ResultSet sarà necessario attendere fino a quando la ricezione di tutti i record nella query. Anche se abbiamo impostato prendere dimensioni 4, per una tabella di 1000 record di, abbiamo ancora finiscono per avere 1000 record in memoria mucchio di application server, è corretto? Fetch dimensioni riguardano solo il numero di andata e ritorno da / a db server.

La mia domanda è, come avviare l'elaborazione su quel 4 (o un qualsiasi numero) registra immediatamente dopo di arrivo di application server, e smaltire per liberare la memoria in assistente di app?

È stato utile?

Soluzione

Penso che si potrebbe utilizzare la stessa soluzione questo . Un gruppo di risultati scorrevole.

Altri suggerimenti

Con un po 'più di informazioni posso ottenere una risposta più utile.

Se si sta utilizzando MySQL:

stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
       java.sql.ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);

http://www.oracle.com/ tecnologia / Tech / java / sqlj_jdbc / htdocs / jdbc_faq.html :

java.util.Properties info = new java.util.Properties();
info.put ("user", "scott");
info.put ("password","tiger");
info.put ("defaultRowPrefetch","15");
getConnection ("jdbc:oracle:oci:@",info);

Se si sta utilizzando JDBC è possibile utilizzare un ResultSet con un cursore che si scorrere attraverso un record alla volta. È necessario fa in modo poi di scrivere il XML in un file di un record alla volta piuttosto che usare DOM per costruire l'XML.

Una regola empirica che ho imparato dalla mia esperienza è che non portare tutti i dati dal database sul server di applicazioni. Una cosa che puoi fare è implementare una procedura alla pagina dei dati.

È possibile portare una pagina di dati contenenti intorno 1000-5000 record, elaborarli, poi di nuovo recuperare i dati per la pagina successiva.

Un concetto per l'esportazione l'intera tabella. (Nota per gli esperti:. Sono consapevole dei suoi difetti)

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
public class FullTableExport {
    public static String toXML(String s) {
        if (s != null) {
            StringBuilder b = new StringBuilder(s.length());
            for (int i = 0, count = s.length(); i < count; i++) {
                char c = s.charAt(i);
                switch (c) {
                case '<':
                    b.append("&lt;");
                    break;
                case '>':
                    b.append("&gt;");
                    break;
                case '\'':
                    b.append("&#39;");
                    break;
                case '"':
                    b.append("&quot;");
                    break;
                case '&':
                    b.append("&amp;");
                    break;
                default:
                    b.append(c);
                }
            }
            return b.toString();
        }
        return "";
    }
    public static void main(String[] args) throws Exception {
        String table = "CUSTOMER";
        int batch = 100;

        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection conn = DriverManager.getConnection(
            "jdbc:oracle:thin:@server:orcl", "user", "pass");
        PreparedStatement pstmt = conn.prepareStatement(
            "SELECT /*+FIRST_ROWS(" + batch + ") */ * FROM " + table);
        ResultSet rs = pstmt.executeQuery();
        rs.setFetchSize(batch);
        ResultSetMetaData rsm = rs.getMetaData();
        File output = new File("result.xml");
        PrintWriter out = new PrintWriter(new BufferedWriter(
            new OutputStreamWriter(
            new FileOutputStream(output), "UTF-8")), false);
        out.printf("<?xml version='1.0' encoding='UTF-8'?>%n");
        out.printf("<table name='%s'>%n", toXML(table));
        int j = 1;
        while (rs.next()) {
            out.printf("\t<row id='%d'>%n", j++);
            for (int i = 1; i <= rsm.getColumnCount(); i++) {
                out.printf("\t\t<col name='%s'>%s</col>%n", 
                    toXML(rsm.getColumnName(i)), 
                    toXML(rs.getString(i)));
            }
            out.printf("\t</row>%n");
        }
        out.printf("</table>%n", table);
        out.flush();
    }
}

Modifica Le carenze (grazie @ J.S.):

  • Non ci sono librerie esterne utilizzate al di là del ojdbc
  • Nulla è chiuso
  • Un'eccezione generica è gettato
  • Si tratta di un metodo main
  • Utilizzo di stampa per la generazione di XML
  • Oracle SQL specifica
  • password di testo normale
  • Alcune colonne guardano imbarazzante nella rappresentazione di stringa
  • UTF-8 è troppo internazionale
  • struttura XML impronta è grande

In quale fase è l'errore che si verifica OOM, è esso su dati di recupero o trattamento di dati a file XML?

Se il suo recupero dei dati, ottenere i dati in batch. Ottenere il numero totale di righe prima, ordina i seleziona dalla chiave primaria e limitare le righe selezionate a dimensioni masticabili.

Se la sua a creare il file XML, inviare il nodo XML di ogni cliente per System.out.println, non tenerlo in memoria. Avviare il programma tramite linea commad e reindirizzare tutto l'output in un file;

java MyConverter > results.txt

Come si esegue un ciclo attraverso il record di tutti viene salvato nel file.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top