我很难在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答案 0 :(得分:2)
来自CachedRowSet
Javadoc(强调我的):
CachedRowSet
对象是断开连接的行集,这意味着它只是短暂地使用与其数据源的连接。 它在读取数据时连接到其数据源,以便用行填充自身,并在将更改传播回其基础数据源时再次连接。其余时间,CachedRowSet
对象断开连接,包括正在修改其数据。
从你的问题:
看起来程序试图用~35,000,000行填充行集,而不考虑pageSize配置
是的,CachedRowSet
将立即从您的数据库中检索35m行,然后它将应用分页和其他已定义的属性。一种可能的解决方案是通过小块处理数据,并在每一行上标记一个标记为已处理。
我建议使用像Pentaho这样的ETL工具来处理这类问题。
答案 1 :(得分:0)
事实上,游标的支持是在postgres JDBC中隐式编码的,如文档中所述。但是,在某些条件下会自动创建光标。