Java类CachedRowSetImpl的奇怪行为

时间:2013-07-16 14:56:32

标签: java postgresql jdbc cachedrowset

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

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

我尝试使用以下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

2 个答案:

答案 0 :(得分:2)

来自CachedRowSet Javadoc(强调我的):

  

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

从你的问题:

  

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

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

我建议使用像Pentaho这样的ETL工具来处理这类问题。

答案 1 :(得分:0)

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

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