0

我在数据库中有很多行,必须对其进行处理,但由于内存限制,我无法将所有数据检索到内存中。

目前,我使用 LIMIT 和 OFFSET 来检索数据以在某个指定的时间间隔内获取数据。

我想知道这是更快的方法还是有另一种方法来从数据库中的表中获取所有数据。将不应用任何过滤器,将处理所有行。

4

2 回答 2

5
SELECT * FROM table ORDER BY column

没有理由将整个表吸入 RAM。只需打开光标并开始阅读。您可以玩具有 fetch 大小的游戏等等,但是当您处理行时,DB 会很高兴地保留它的位置。

附加物:

好的,如果您使用的是 Java,那么我很清楚您的问题是什么。

首先,仅通过使用 Java,您就在使用游标。这基本上就是 Java 中的 ResultSet。一些结果集比其他结果集更灵活,但其中 99% 很简单,只转发您调用“下一个”以获取每一行的结果集。

现在关于你的问题。

问题出在 Postgres JDBC 驱动程序上。我不知道他们为什么这样做,也许是规范,也许是别的东西,但无论如何,Postgres 有一个奇怪的特性,即如果您的 Connection 将 autoCommit 设置为 true,那么 Postgres 决定在任一execute 方法或第一个 next 方法。至于在哪里并不重要,只有当你有无数行时,你会得到一个很好的 OOM 异常。没有帮助。

这很容易就是你所看到的,我很欣赏它是多么令人沮丧和困惑。

大多数连接默认为 autoCommit = true。相反,只需将 autoCommit 设置为 false。

Connection con = ...get Connection...
con.setAutoCommit(false);
PreparedStatement ps = con.prepareStatement("SELECT * FROM table ORDER BY columm");
ResultSet rs = ps.executeQuery();
while(rs.next()) {
    String col1 = rs.getString(1);
    ...and away you go here...
}
rs.close();
ps.close();
con.close();

请注意明显缺乏异常处理,留给读者练习。

如果您想更好地控制一次将多少行提取到内存中,您可以使用:

ps.setFetchSize(numberOfRowsToFetch);

玩弄它可能会提高你的表现。

如果您完全关心排序,请确保您在 ORDER BY 中使用的列上有适当的索引。

于 2011-07-19T17:56:28.097 回答
1

由于它根据您的评论清除了您使用 Java:

如果您使用的是 JDBC,您将希望使用:http: //download.oracle.com/javase/1.5.0/docs/api/java/sql/ResultSet.html

如果您使用的是 Hibernate,它会变得更棘手: http ://docs.jboss.org/hibernate/core/3.3/reference/en/html/batch.html

于 2011-07-20T03:09:56.273 回答