我在数据库中有很多行,必须对其进行处理,但由于内存限制,我无法将所有数据检索到内存中。
目前,我使用LIMIT和OFFSET来检索数据,以便在某个特定的时间间隔内获取数据。
我想知道这是更快的方式还是有另一种方法从数据库中的表中获取所有数据。将不使用任何过滤器,将处理所有行。
答案 0 :(得分:5)
SELECT * FROM table ORDER BY column
没有理由把整张桌子吸进RAM。只需打开光标即可开始阅读。你可以玩带有提取大小的游戏,但是你可以在处理你的行时愉快地保留它的位置。
附录:
好的,如果您正在使用Java,那么我很清楚您的问题是什么。
首先,只需使用Java,就可以使用游标了。这基本上是Java中的ResultSet。一些ResultSet比其他ResultSet更灵活,但其中99%都是简单的,只转发ResultSet,你可以在下一行调用每行。
现在你的问题。
问题特别在于Postgres JDBC驱动程序。我不知道为什么他们这样做,也许是规格,也许是别的,但无论如何,Postgres有一个奇怪的特征,即如果你的Connection有autoCommit设置为true,那么Postgres决定在整个结果集上吸吮执行方法或第一个下一个方法。对于哪里来说并不重要,只有当你拥有大量的行时,才能获得一个不错的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中使用的列上有适当的索引。
答案 1 :(得分: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