簡體   English   中英

OutOfMemoryError:Java堆空間

[英]OutOfMemoryError: Java heap space

我在使用Java OutOfMemoryError時遇到問題。 該程序基本上會查看在mysql工作台上運行的mysql表,並查詢它們以獲取某些信息,然后將它們放入CSV文件中。

該程序可以在較小的數據集上正常運行,但是一旦我使用較大的數據集(數小時而不是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 

請隨時詢問您是否需要源代碼或更多信息,因為我迫切希望解決此問題!

謝謝。

SELECT * FROM log, cpuinfo, memoryinfo將確保給出巨大的結果集。 它將給出所有3個表中所有行的笛卡爾乘積。

在沒有看到表結構(或不知道期望的結果)的情況下,很難找到解決方案,但是我懷疑您要么想要某種連接條件來限制結果集,要么使用UNION a'la;

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

...這將為您提供所有3個表中Process所有不同值。

您的第二條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

看起來您正在嘗試同時從所有3個日志中進行選擇,但最終得到了另一個笛卡爾積。 您確定要得到期望的結果集嗎?

您可以使用LIMIT estatementet限制SQL查詢返回的結果。

例如:

 SELECT * FROM `your_table` LIMIT 100

這將返回前100個結果

SELECT * FROM `your_table` LIMIT 100, 200

這將返回結果100到200

顯然,您可以迭代這些值,以便無論有多少元素,您都可以訪問數據庫中的所有元素。

我認為您正在同一內存中加載太多數據。 嘗試在sql語句中使用offsetlimit ,以便可以避免此問題

您的Java代碼正在執行數據庫可以更有效地執行的操作。 從query1a看來,您真正想要的只是唯一的過程。 select distinct Process from ...應該足以做到這一點。

然后,仔細考慮該查詢中需要哪些表。 您是否真的需要log,cpuinfo和memoryinfo? 如Joachim Isaksson所述,這將返回這三個表的笛卡爾積,從而為您提供x * y * z行(其中x,y和z是這三個表中每個表的行數)和a + b + c列(其中a,b和c是每個表中的列數)。 我懷疑那是您想要或需要的。 我假設您可以從一個表或三個表的聯合(而不是聯接)中獲得那些獨特的過程。

最后,您的第二個循環和查詢實際上是在進行聯接,這又將更好,更有效地留給數據庫。

就像其他人所說的那樣,以較小的塊獲取數據可能會解決此問題。 這是stackoverflow中討論此問題的其他線程之一: 如何從大表中讀取所有行?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM