0

我很难在 java 中使用 CachedRowSetImpl 类。我想分析一个巨大的 postgres 表的数据,其中包含约 35,000,000 行和 3 个整数列。

我无法将所有内容加载到我的计算机物理内存中,然后我想每批 100000 行读取这些行。在 psql 提示符或 pgadmin 等图形界面中执行相应的查询(select col1,col2,col3 from theTable limit 10000)时,加载这 100000 行和几兆内存大约需要 4000ms。

我尝试使用以下 java 代码执行相同的操作:

CachedRowSet rowset = new CachedRowSetImpl();
int pageSize=1000000;
rowset.setCommand("select pk_lib_scaf_a,pk_lib_scaf_b,similarity_evalue from from_to_scaf");
rowset.setPageSize(pageSize);
rowset.setReadOnly(true);
rowset.setFetchSize(pageSize);
rowset.setFetchDirection(ResultSet.FETCH_FORWARD);
rowset.execute(myConnection);

System.out.println("start !");

while (rowset.nextPage()) {
    while (rowset.next()) {
        //treatment of current data page

    } // End of inner while
    rowset.release();
} 

运行上述代码时,“开始!” 消息永远不会显示在控制台中,并且执行似乎卡在 rowset.execute() 行中。此外,内存消耗变得疯狂并达到我计算机物理内存(8gb)的极限。

这很奇怪,看起来程序试图用大约 35,000,000 行填充行集,而不考虑 pageSize 配置。

有没有人在使用 java JDBC 和 postgres 驱动程序时遇到过这样的问题?我想念什么?

postgres 9.1 java jdk 1.7

4

2 回答 2

2

来自CachedRowSetJavadoc(强调我的):

一个CachedRowSet对象是一个断开连接的行集,这意味着它只是短暂地使用到它的数据源的连接。它在读取数据以用行填充自身时连接到其数据源,并在将更改传播回其底层数据源时再次连接到它。其余时间,CachedRowSet对象断开连接,包括在修改其数据时。

从你的问题:

看起来程序试图用〜35,000,000行填充行集,而不考虑pageSize配置

是的,CachedRowSet将立即从您的数据库中检索 35m 行,然后应用分页和其他定义的属性。一种可能的解决方案是按小块处理数据,并在每一行上都有一个标志以将其标记为已处理。

我会推荐使用像Pentaho这样已经可以处理此类问题的 ETL 工具。

于 2013-07-16T17:56:51.513 回答
0

事实上,对 cursor 的支持在 postgres JDBC 中被隐式编码,如其文档中所述。但是,在某些条件下会自动创建游标。

http://jdbc.postgresql.org/documentation/head/query.html

于 2013-07-17T10:08:06.130 回答