抓到:java.lang.OutOfMemoryError:Java堆空间 - 使用-Xmx不适用

时间:2011-08-01 20:54:02

标签: groovy jvm out-of-memory

我在Groovy中编写了一个非常复杂的数据库迁移脚本,它在我的工作站上运行得很好,但在服务器的JVM上运行时会产生“Caught:java.lang.OutOfMemoryError:Java堆空间”。 JVM保持原样(作为实习生的资源有限),所以除了增加可用内存之外,我还需要找出解决这个问题的另一种方法。

当访问一些最大的表时出现错误:一个特别大但很简单的连接(200,000多行到50,000多行)。有没有其他方法可以接近这样的联接,这将使我免于错误?

查询示例:

target.query(""" 
    SELECT 
        a.*, b.neededColumn 
    FROM 
        bigTable a JOIN mediumTable b ON 
    a.stuff = b.stuff 
    ORDER BY stuff DESC 
""") { ResultSet rs ->
    ...
}

2 个答案:

答案 0 :(得分:2)

您可以在数据库服务器上运行SQL连接吗?

如果没有,你可能会坚持迭代你的200,000个结果中的每一个,将它加入50,000行并写出结果(所以你不会在任何时候在内存中存储超过1 * 50,000的结果)

或者,如果您可以访问多台计算机,您可以将200,000个项目划分为多个块并为每台计算机执行一个块?

修改

使用您的示例代码,您应该可以:

new File( 'output.csv' ).withWriter { w ->
  target.eachRow( '''SELECT a.a, a.b, a.c, b.neededColumn FROM
    bigTable a
    JOIN mediumTable b ON a.stuff = b.stuff
    ORDER BY stuff DESC''' ) { row ->
    w.write "$row.a,$row.b,$row.c,$row.neededColumn"
  }
}

这会将每一行写入文件output.csv

答案 1 :(得分:1)

您必须更改代码,以便不会同时将所有行全部加载到内存中(即,流式传输数据,一次一行地处理每一行)。据我所知,当您使用collect之类的东西时,Groovy仍然不会这样做,所以重写它以使用for循环。