Pergunta

Eu sou dado uma tarefa de converter uma enorme mesa para o arquivo XML personalizado. Eu vou estar usando Java para este trabalho.

Se eu simplesmente emitir um "SELECT * FROM cliente", ele pode retornar enorme quantidade de dados que, eventualmente, causando OOM. Eu me pergunto, se existe uma maneira que eu posso processar o registro imediatamente, uma vez que se tornam disponíveis, e remover o registro da memória depois que durante o processo de recuperação sql?

--- editado em 13 Jul 2009

Deixe-me explicar a minha pergunta. Eu tenho um servidor db e um servidor de aplicativos. Quando eu emitir uma consulta seleção no aplicativo, os dados irão viajar de servidor db para servidor de aplicações.

Eu acredito que (me corrija se eu estiver errado) ResultSet terá que esperar até receber todos os registros na consulta. Mesmo se definir buscar tamanho 4, para uma mesa de 1000 registro, nós ainda acabam por ter 1000 registros na memória heap do servidor de aplicações, é correto? Fetch tamanho afetam apenas o número de ida e volta de / para o servidor de banco de dados.

A minha pergunta é, como para iniciar o processamento em que 4 (ou qualquer número) registra imediatamente após a sua chegada ao servidor de aplicações, e eliminá-lo para liberar memória no servidor de aplicações?

Foi útil?

Solução

Eu acho que você poderia usar a mesma solução que este . Um conjunto de resultados de rolagem.

Outras dicas

Com um pouco mais de informação posso obter uma resposta mais útil.

Se você estiver usando 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 / tecnologia / 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 você estiver usando JDBC você pode usar um ResultSet com um cursor que você iterate através de um registro de cada vez. Você precisa torna-se, então, que você escrever seu XML para um registro de arquivo de cada vez ao invés de usar DOM para construir o XML.

Uma regra de ouro que eu aprendi com a minha experiência é que você nunca trazer todos os dados do banco de dados para o servidor de aplicativos. Uma coisa que você pode fazer é implementar um procedimento para a página seus dados.

Você pode trazer uma página de dados contendo cerca de 1000-5000 registros, processá-los, então, novamente buscar os dados para a próxima página.

Um conceito para exportar a tabela inteira. (Nota aos especialistas:. Estou ciente de suas deficiências)

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();
    }
}

Editar As deficiências (graças @ J.S..):

  • Nenhuma biblioteca externa usados ??além do ojdbc
  • Nada está fechado
  • A exceção genérica é lançado
  • É um método main
  • O uso de impressão para a geração de XML
  • específica SQL do Oracle
  • senha de texto simples
  • Algumas colunas olhar estranho em representação de cadeia
  • UTF-8 é muito internacional
  • estrutura XML pegada é grande

Em que fase está ocorrendo o erro OOM, é sobre a recuperação de dados ou processamento de dados para arquivo XML?

Se recuperação de seus dados, obter os dados em lotes. Obter o número total de linhas em primeiro lugar, ordenar os seleciona pela chave primária e limitar as linhas selecionadas para tamanhos mastigáveis.

Se a sua a criar o arquivo XML, enviar o nó XML de cada cliente para System.out.println, não segurá-la na memória. Inicie o programa através da linha commad e redirecionar toda a saída para um arquivo;

java MyConverter > results.txt

Como você percorrer o registro de tudo é salvo no arquivo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top