我有一个包含 800 万条记录的数据库,我需要用 Java 编写的特定方式处理这些记录。在查找了一些东西后,我发现了以下相关帖子: Efficient way to go over result set in Java Fastest way to iterate through large table using JDBC how do I load 100 million rows in to memory Retrieving a million records from a database 这是我的代码,它返回存储在我的 MySQL 数据库的标签列中的项目:public ResultSet getAllTags() { String query = "SELECT Tags FROM dataset"; ResultSet rs = null; try { connection = ConnectionFactory.getConnection(DATABASE); preparedStatement = connection.prepareStatement(query, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); preparedStatement.setFetchSize(Integer.MIN_VALUE); rs = preparedStatement.executeQuery(query); // following line is for testing, to see what comes out of the resultset System.out.println("output: " + rs.getString(1)); return rs; } catch (Exception ex) { ex.printStackTrace(); return null; } finally { closeAll(); }}在这里,我返回 ResultSet 以便我处理 rs.next() 循环中的每一行。但是,在 rs = preparedStatement.executeQuery(query); 行它开始吃掉我计算机的所有可用内存(我在 Mac OSX 上工作,内存为 8GB。只有 Eclipse 打开时,我还有 +/- 5GB 可用空间,运行应用程序时它会下降到 有人可以解释我做错了什么,以及为什么即使我按照其他具有类似记录数量的页面上的说明也会出现此问题? 最佳答案 您唯一做错的是使用愚蠢的数据库驱动程序 (MySQL),默认情况下,它会读取内存中的整个结果集。尝试使用 http://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html 中描述的 useCursorFetch 和 defaultFetchSize 属性来避免这种情况,并且您应该能够遍历行而无需获取内存中的所有内容(虽然未测试)。请注意,该行System.out.println("output: " + rs.getString(1));将抛出异常,因为您尚未在结果集中调用 next()。另请注意,如果 closeAll() 关闭连接,调用者将无法遍历结果集,因为它将被关闭。您应该在关闭连接之前执行迭代。请注意,驱动程序的 the documentation 说:By default, ResultSets are completely retrieved and stored in memory. In most cases this is the most efficient way to operate, and due to the design of the MySQL network protocol is easier to implement. If you are working with ResultSets that have a large number of rows or large values, and cannot allocate heap space in your JVM for the memory required, you can tell the driver to stream the results back one row at a time.To enable this functionality, create a Statement instance in the following manner:stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY);stmt.setFetchSize(Integer.MIN_VALUE);但是您使用的是 TYPE_SCROLL_SENSITIVE 而不是 TYPE_FORWARD_ONLY 。关于java - 从数据库中读取 +800 万条记录的内存泄漏,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22577433/
10-12 06:06