Как избежать OOM (из памяти) ошибок при получении всех записей из таблицы огромной?

Обновить

November 2018

Просмотры

27.5k раз

15

Я дал задание, чтобы преобразовать огромный стол в пользовательский файл XML. Я буду использовать Java для этой работы.

Если я просто вопрос «SELECT * FROM клиента», он может возвращать огромное количество данных, которые в конечном счете, в результате чего OOM. Интересно, есть ли способ я могу обработать запись сразу, как только он станет доступен, и удалить запись из памяти после того, что во время процесса извлечения SQL?

--- изм 13 июл 2009

Позвольте мне уточнить мой вопрос. У меня есть 1 сервер БД и 1 сервер приложений. Когда я выполняю запрос на выборку в приложении, данные будут путешествовать из БД сервера для сервера приложений.

Я считаю (поправьте меня, если я ошибаюсь) ResultSet нужно будет ждать, пока не получит все записи в запросе. Даже если мы устанавливаем размер выборки как 4, для 1000-таблицы рекордов, мы до сих пор в конечном итоге, 1000 записей в куче памяти сервера приложений, это правильно? Принеси размер влияет только на количество поездка туда и обратно из / в БД сервера.

Мой вопрос, как начать обработку на что 4 (или любом количестве) записях сразу после его прибытия в приложении-сервер, и размещает его, чтобы освободить память в серверах приложений?

6 ответы

4

Первое правило, что я узнал из моего опыта, что вы никогда не Привести все данные из базы данных на сервер приложений. Одна вещь, которую вы можете сделать, это реализовать процедуру страницы ваших данных.

Вы можете принести одну страницу данных, содержащих около 1000-5000 записей, обрабатывать их, а затем снова получать данные для следующей страницы.

0

На каком этапе происходит ошибка ООМ, это на поисковых или обработки данных, данных в файл XML?

Если его извлечения данных, получить данные в пакетном режиме. Получить общее количество строк первым, заказать выбирает с помощью первичного ключа и ограничить строки, выбранные для жевательных размеров.

Если его при создании файла XML, отправить XML-узел каждого клиента System.out.println, не держать его в памяти. Запуск программы через commad линии и перенаправить весь вывод в файл;

java MyConverter > results.txt

Как вы проходные записей все сохраняется в файле.

4

Я думаю , вы могли бы использовать такое же решение , как этот . Прокручиваемый ResultSet.

6

С немного больше информации я могу получить более полезный ответ.

Если вы используете 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/technology/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);
4

Если вы используете JDBC вы можете использовать ResultSet с курсором, который вы итерацию через одну запись одновременно. Вы должны убеждается то, что вы пишете XML в файл одной записи в то время, а не с помощью DOM для создания XML.

1

Концепция для экспорта всей таблицы. (Примечание для экспертов: Я знаю его недостатки.)

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

Редактировать недочёты (спасибо @JS):

  • Никаких внешних библиотек, используемых за пределами ojdbc
  • Ничто не закрыто
  • Родовое исключение
  • Это является основным методом
  • Использование печати для генерации XML
  • Oracle конкретный SQL
  • Обычный текст пароля
  • Некоторые столбцы выглядят неуклюжими в строковом представлении
  • UTF-8 является слишком международным
  • Структура XML след большой