【发布时间】:2023-04-05 07:19:02
【问题描述】:
如何在 java 中获取大型结果集?我有大约 140,000 行 3 列。
【问题讨论】:
-
好吧,就像在 java 中获取小结果集一样。你有什么顾虑?性能、内存使用、...?
标签: java sql performance oracle jdbc
如何在 java 中获取大型结果集?我有大约 140,000 行 3 列。
【问题讨论】:
标签: java sql performance oracle jdbc
没有特殊的方法可以检索大型结果集;这可以像通过 JDBC 进行的任何其他数据库查询一样完成。
关键在于如何处理结果。 140,000 条小记录并不算多,但如果一次将它们全部保存在应用程序内存中是一个问题,请考虑是否可以“流式”处理它们。也就是说,使用每条记录所需的信息,然后在检索下一条记录之前丢弃该记录。这样,内存需求就不再取决于结果集中的记录数。
【讨论】:
(使用 java.sql.Connection 到您的数据库):
Statement st = cnxn.createStatement();
ResultSet rs = st.executeQuery("SELECT column1,column2,your_mom FROM some_table");
while(rs.next()){
Object ob1 = rs.getObject(1);
Object ob2 = rs.getObject(2);
Ho ob3 = rs.getHo(3);
doStuffWithRow(ob1,ob2,ob3);
}
除非您的 DBMS 毫无用处,否则结果将按要求从磁盘/内存中读取,并且不会留在您的内存中或任何类似的疯狂内容中。使用基于基元的 ResultSet.getXXX 方法比 getObject 更快,但我不想指定列类型。
请耐心等待。哦,在这里远离 ORM。
【讨论】:
connection 上调用 setAutoCommit(false),然后在 preparedStatement 上调用 setFetchSize(FETCH_SIZE)。但是流式获取 api 是按驱动程序实现的,并且在整个 jdbc 上并不一致。很烦人。
如果您使用的是 PostgreSQL,则需要按如下方式设置连接和语句:
Connection cnxn = ...;
cnxn.setAutoCommit(false);
Statement stmnt = cnxn.createStatement();
stmnt.setFetchSize(1);
否则,您的查询可能会尝试将所有内容加载到内存中。 感谢 http://abhirama.wordpress.com/2009/01/07/postgresql-jdbc-and-large-result-sets/ 记录这一点。
【讨论】:
我会避免使用任何类型的复杂抽象加载这样的数据集。这听起来像是一个“批处理作业”风格的应用程序。
我会推荐使用原始 jdbc 并将其映射到一个非常紧凑的表示,没有膨胀只有 3 列这应该很容易保存在内存中,如果字符串?不会太大。
避免使用 hibernate 等工具加载 140k 行。这是一个很棒的工具,但如果你在休眠的一级和二级缓存中保存了这么多实体,你可能会遇到内存问题。
【讨论】:
我建议使用批处理样式获取而不是加载所有内容。执行具有大结果集的查询时,在数据库端有性能考虑。
【讨论】: