JDBC是一个很大的记忆力吗?

时间:2009-11-13 15:07:32

标签: java performance memory jdbc

我需要在我的java代码中从数据库重复访问(读入)数据,因此采用了JDBC。但是,在我看来,使用JDBC占用了大量内存。我试着要小心关闭为JDBC创建的对象(ResultSet,Statemenet),但是与从文本文件中读取输入相比,它似乎仍然占用了很多记忆。有人知道减少记忆消费的最佳方法吗?谢谢。

8 个答案:

答案 0 :(得分:4)

JDBC不会为自己占用太多内存。它缓存了几个元数据,但绝大多数内存通常都被查询结果占用。它的想法只是提供一个访问您的数据的标准接口,它本身并不是一个实现。这就是为什么您需要JDBC驱动程序来实现每个数据库产品的细节。

JDBC不是资源密集型,因为即使在具有JavaME的移动设备上也可以运行JDBC - 这是一个资源非常有限的环境。

因此,虽然您可能会欣赏使用Hibernate或JPA等框架更轻松地处理数据,但您不必担心JDBC会消耗在整个应用程序环境中值得一提的任何数量的资源。

正如他们所说:不要试图优化那些不是问题的东西:)

答案 1 :(得分:3)

JDBC不是内存耗尽。它返回的数据可能是一个巨大的记忆力。

JDBC的一个常见问题是,包含大量数据(并且不总是内存优化)的结果集未得到正确处理或关闭。为了防止来自ResultSet对象的内存泄漏,开发人员必须采取谨慎的步骤以确保在继续之前释放内存。 (处理大多数内存清理的Java意味着这对大多数开发人员来说都是一个盲点,所以这并不奇怪。)

考虑使用此代码。它使用“try / catch try / finally”模式来明确地关闭结果集:

try{
    Statement stmt = conn.createStatement();
    try {
        ResultSet rs = stmt.createQuery("some sql");
        try {
            // ResultSet processing goes here
        } finally {
            rs.close();
        }
    } finally {
        stmt.close();
    }
}
catch ( SQLException ex ) { // exception processing for any problems. }

这可以保证结果集关闭 - 即使抛出异常也是如此。

答案 2 :(得分:2)

“JDBC”不太可能是内存耗尽。 JDBC只是一个管道。使用的内存量取决于您正在与哪个数据库进行通信,更重要的是,您正在运行的查询类型以及是否正确使用游标。

在处理大量数据时,您可以查看Hibernate以获取有关管理内存使用情况的帮助。

答案 3 :(得分:2)

如果您遇到过这个问题,那么它可能是您自己的代码,这是一个内存耗尽。如果将完整的数据库内容转移到Java的内存中,就会发生这种情况。这实际上不是JDBC的错。

为减少内存消耗,最好是尽可能具体的SQL查询。只需查询您实际所需的数据,不需要其他内容。

如果您确实需要表的所有数据,那么您可能正在使用错误的JDBC工具。体面的DB服务器附带了更好的导入/导出工具。先看看它。

答案 4 :(得分:2)

我必须同意其他人在这里所说的,JDBC本身不会占用大量内存。但是,如果您担心使用大量内存的特定JDBC操作,可以使用JConsole或分析器来查看在所述方法执行期间使用了多少堆。

答案 5 :(得分:2)

我想在自己遇到内存问题之后在这里添加一个重点:

我正在从MySQL数据库中读取大型数据集(大约600,000行,每列20列)并且仍然没有堆空间。我以为我可以通过更改提取大小来修复它,但是在PreparedStatement上设置提取大小什么也没做。

我发现我使用的MySQL JDBC驱动程序(版本5.1.15)没有实现提取大小。实际上,对于每个MySQL查询,它都会将整个ResultSet加载到内存中。但是,如果将获取大小设置为Integer.MIN_VALUE,则驱动程序将一次从MySQL服务器加载1行....但有一点需要注意:在ResultSet关闭之前,您无法在连接上执行任何其他语句。 / p>

这里记录了:

http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-implementation-notes.html

话虽这么说,如果您可以控制MySQL服务器,您可以将'useCursorFetch'设置为true,服务器将返回'defaultFetchSize'行数而不是所有行。从MySQL 5.0.2版本开始就是如此。开发人员声称这是一个实验性黑客,所以请注意:http://forums.mysql.com/read.php?39,137457,137457#msg-137457

无论如何,这里故事的道德是检查你使用的JDBC驱动程序是否有任何特殊性。

答案 6 :(得分:1)

它是您加载的数据的一个因素,而不是JDBC库。由于JDBC调用涉及大量数据,因此我会检查在没有被释放的集合中没有很多对象,并将它放到堆的第2代。

答案 7 :(得分:0)

如果您正在执行从数据库返回许多行的查询,并且JDBC驱动程序不支持滚动结果集,则JDBC可以使用大量内存。这会导致从服务器检索所有行,并可能加载到RAM中。

解决方案是将查询拆分为较小的批次,或者尽可能启用滚动结果集。