【问题标题】:OutOfMemoryError: Java heap spaceOutOfMemoryError:Java 堆空间
【发布时间】:2013-01-24 07:59:03
【问题描述】:

我遇到了 java OutOfMemoryError 的问题。该程序主要查看在 mysql workbench 上运行的 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 

请随时询问您是否需要源代码或更多信息,因为我急于解决这个问题!

谢谢。

【问题讨论】:

  • 你试过用profiler吗?
  • 您不能将数据库中的结果流式传输到文件中,而无需同时将所有内容都保存在内存中吗?
  • writer.close() i.o.冲洗(在循环内)。许多改进代码的机会;雇用一名程序员。

标签: java mysql csv out-of-memory


【解决方案1】:

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 个日志中进行选择,但最终得到了另一个笛卡尔积。你确定你得到了你期望的结果集吗?

【讨论】:

  • 用打印行测试,你是对的,在我尝试你提到的第一个选择后它给出了错误。如果不是这样,我如何从所有三个表中提取所有数据?当我只有“log”和 cpuinfo”,没有“AND memoryinfo..”并且没有“= memoryinfo.Timestamp”时,第二个 sql 语句曾经工作,所以我假设添加它们只会带来下一个表(我需要一次全部选择它们以位于同一个csv文件中)。我类似地添加了cpuinfo的东西并且它起作用了。
  • 如果您只想从所有表中获取Process,只需使用SELECT Process FROM log UNION SELECT Process FROM cpuinfo UNION SELECT Process FROM memoryinfo。请参阅上面的编辑。
【解决方案2】:

您可以使用 LIMIT Estatementet 限制 SQL 查询返回的结果。

例如:

 SELECT * FROM `your_table` LIMIT 100

这将返回前 100 个结果

SELECT * FROM `your_table` LIMIT 100, 200

这将返回从 100 到 200 的结果

显然,您可以使用这些值进行迭代,这样无论有多少,您都可以访问数据库中的所有元素。

【讨论】:

    【解决方案3】:

    我认为您在内存中同时加载了太多数据。尝试在你的sql语句中使用offsetlimit,这样就可以避免这个问题

    【讨论】:

      【解决方案4】:

      您的 Java 代码正在执行数据库可以更有效地执行的操作。从 query1a 看来,您真正想要的只是独特的流程。 select distinct Process from ... 应该足以做到这一点。

      然后,仔细考虑该查询中需要哪些表或表。你真的需要 log、cpuinfo 和 memoryinfo 吗?正如 Joachim Isaksson 提到的,这将返回这三个表的笛卡尔积,为您提供 x * y * z 行(其中 x、y 和 z 是这三个表中每个表中的行数)和 a + b + c 列(其中 a、b 和 c 是每个表中的列数)。我怀疑那是你想要或需要的。我假设您可以从一个表或三个表的联合(而不是连接)中获取这些独特的进程。

      最后,您的第二个循环和查询本质上是在进行连接,这又一次更好、更高效地留给了数据库。

      【讨论】:

        【解决方案5】:

        正如其他人所说,以较小的块获取数据可能会解决问题。 这是 stackoverflow 中讨论此问题的其他线程之一: How to read all rows from huge table?

        【讨论】:

          猜你喜欢
          • 2019-03-06
          • 2015-08-25
          • 2021-02-13
          • 2012-10-09
          • 2020-09-14
          • 1970-01-01
          • 1970-01-01
          • 2012-06-21
          • 1970-01-01
          相关资源
          最近更新 更多