一尘不染

从数据库检索顺序数据的最快方法是什么?

sql

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

此刻,我使用LIMIT和OFFSET来检索数据,以指定的时间间隔获取数据。

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


阅读 128

收藏
2021-05-16

共1个答案

一尘不染

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上使用的列上具有适当的索引。

2021-05-16