繁体   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