我在数据库中有很多行,必须对其进行处理,但是由于内存限制,我无法将所有数据检索到内存中。
此刻,我使用LIMIT和OFFSET来检索数据,以指定的时间间隔获取数据。
我想知道这是不是更快的方法,还是有另一种方法可以从数据库中的表中获取所有数据。将不应用任何过滤器,将处理所有行。
SELECT * FROM table ORDER BY column
没有理由将整个表都吸入RAM。只需打开光标并开始阅读。您可以玩具有抓取大小的游戏,但不可以,但数据库在处理行时会很乐意保留其位置。
附加物:
好的,如果您使用的是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上使用的列上具有适当的索引。