2013-02-08 3 views
0

У меня проблема с java OutOfMemoryError. Программа в основном рассматривает таблицы mysql, которые работают в workbench mysql, и запрашивает их для получения определенной информации, а затем помещает их в файлы CSV.OutOfMemoryError: Java heap space

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

Настройка аргументов Java VM на -xmx1024m работала для немного большего набора данных, но мне нужно, чтобы он обрабатывал еще большие, но при этом дает ошибку.

Вот метод, который я совершенно уверен, что является причиной этой программы где-то:

// CSV is csvwriter (external lib), sment are Statements, rs is a ResultSet 
public void pidsforlog() throws IOException 
{ 
    String[] procs; 
    int count = 0; 
    String temp = ""; 

    System.out.println("Commence getting PID's out of Log"); 
    try { 
     sment = con.createStatement(); 
     sment2 = con.createStatement(); 
     String query1a = "SELECT * FROM log, cpuinfo, memoryinfo"; 
     rs = sment.executeQuery(query1a); 
     procs = new String[countThrough(rs)]; 

     // SIMPLY GETS UNIQUE PROCESSES OUT OF TABLES AND STORES IN ARRAY 
     while (rs.next()) { 
      temp = rs.getString("Process"); 

      if(Arrays.asList(procs).contains(temp)) { 
      } else { 
       procs[count] = temp; 
       count++; 
      } 
     } 

     // BELIEVE THE PROBLEM LIES BELOW HERE. SIZE OF THE RESULTSET TOO BIG? 
     for(int i = 0; i < procs.length; i++) { 
      if(procs[i] == null) { 
      } else { 
       String query = "SELECT DISTINCT * FROM log, cpuinfo, memoryinfo WHERE log.Process = " + "'" + procs[i] + "'" + " AND cpuinfo.Process = " + "'" + procs[i] + "'" + " AND memoryinfo.Process = " + "'" + procs[i] + "' AND log.Timestamp = cpuinfo.Timestamp = memoryinfo.Timestamp"; 
       System.out.println(query); 
       rs = sment.executeQuery(query); 

       writer = new CSVWriter(new FileWriter(procs[i] + ".csv"), ','); 
       writer.writeAll(rs, true); 
       writer.flush(); 
      } 
     } 
     writer.close(); 
    } catch (SQLException e) { 
     notify("Error pidslog", e); 
    } 
}; // end of method 

Пожалуйста, не стесняйтесь спросить, если вы хотите, исходный код или больше информации, как я в отчаянии, чтобы получить это фиксированное !

Спасибо.

+0

Вы пытались использовать [профилировщик] (http://profiler.netbeans.org/)? – user000001

+0

Не можете ли вы передать результаты из базы данных в файл, не имея сразу все в памяти? – kutschkem

+0

'writer.close()' i.o. заподлицо (внутри петли). Много возможностей улучшить код; нанять программиста. –

ответ

0

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

2

обязательно предоставит огромный набор результатов. Это даст декартово произведение всех строк во всех трех таблицах.

Не видя структуру таблицы (или не зная желаемого результата), трудно определить решение, но я подозреваю, что вы либо хотите какие-то условия соединения, чтобы ограничить набор результатов, либо использовать UNION a'la;

SELECT Process FROM log 
UNION 
SELECT Process FROM cpuinfo 
UNION 
SELECT Process FROM memoryinfo 

... который будет просто дать вам все различные значения для Process во всех 3-х таблиц.

Ваш второй оператор SQL также выглядит немного странно;

SELECT DISTINCT * 
FROM log, cpuinfo, memoryinfo 
WHERE log.Process = @param1 
    AND cpuinfo.Process = @param1 
    AND memoryinfo.Process = @param1 
    AND log.Timestamp = cpuinfo.Timestamp = memoryinfo.Timestamp 

Похоже, вы пытаетесь выбрать из всех трех журналов одновременно, но в конечном итоге с другим декартовым продуктом. Вы уверены, что получаете набор результатов, который вы ожидаете?

+0

Протестировано печатными линиями, и вы правы, что это дает ошибку после того, как я попытаюсь выбрать первый выбранный вами вариант. Как я могу вытащить все данные из всех трех таблиц, если не так? Второй оператор sql, используемый для работы, когда у меня были только «log» и cpuinfo », без« AND memoryinfo .. »и без« = memoryinfo.Timestamp », поэтому я предположил, что их добавление просто приведет к следующей таблице в (я должен выбрать их все сразу, чтобы быть в одном и том же файле csv). Я добавил материал cpuinfo аналогичным образом, и он сработал. – fypfyp

+0

Если вы просто хотите 'Process' из всех таблиц, просто выполните SELECT Process FROM log UNION SELECT Process FROM cpuinfo UNION SELECT Process FROM memoryinfo' вместо этого. См. Редактирование выше. –

1

Вы можете ограничить результат, возвращаемый вашими SQL-запросами, с помощью LIMIT estatementet.

Например:

SELECT * FROM `your_table` LIMIT 100 

Это вернет первые 100 результатов

SELECT * FROM `your_table` LIMIT 100, 200 

Это будет возвращать результаты от 100 до 200

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

0

Ваш код Java делает то, что база данных могла бы сделать более эффективно. Из query1a, похоже, все, что вы действительно хотите, это уникальные процессы. select distinct Process from ... должно быть достаточно для этого.

Затем тщательно подумайте о том, какие таблицы или таблицы необходимы в этом запросе. Вам действительно нужны журналы, cpuinfo и memoryinfo? Как отметил Иоахим Исакссон, это вернет декартово произведение этих трех таблиц, предоставив вам строки x * y * z (где x, y и z - количество строк в каждой из этих трех таблиц) и a + b + c (где a, b и c - количество столбцов в каждой из таблиц). Я сомневаюсь, что это то, что вам нужно или нужно. Я предполагаю, что вы можете получить эти уникальные процессы из одной таблицы или объединения (а не объединения) трех таблиц.

Наконец, ваш второй цикл и запрос по существу делают соединение, что-то снова лучше и более эффективно уходит в базу данных.

0

Как и другие пользователи, выбор данных в небольших кусках может решить проблему. Это один из других потоков в StackOverflow, что переговоры по этому вопросу: How to read all rows from huge table?

Смежные вопросы