数据库 - 连接配置引起的OOM
时间:2021-07-01 10:21:17
帮助过:20人阅读
public void testReadTimeout() throws SQLException {
Connection connection =
dataSource.getConnection();
//https://jdbc.postgresql.org/documentation/head/query.html
connection.setAutoCommit(
false);
//NOTE 为了设置fetchSize,必须设置为false
String sql =
"select * from demo_table";
PreparedStatement pstmt;
try {
pstmt =
(PreparedStatement)connection.prepareStatement(sql);
pstmt.setFetchSize(50);
System.out.println(
"ps.getQueryTimeout():" +
pstmt.getQueryTimeout());
System.out.println(
"ps.getFetchSize():" +
pstmt.getFetchSize());
System.out.println(
"ps.getFetchDirection():" +
pstmt.getFetchDirection());
System.out.println(
"ps.getMaxFieldSize():" +
pstmt.getMaxFieldSize());
ResultSet rs =
pstmt.executeQuery();
//NOTE 这里返回了就代表statement执行完成,默认返回fetchSize的数据
int col =
rs.getMetaData().getColumnCount();
System.out.println(
"============================");
while (rs.next()) {
for (
int i =
1; i <= col; i++
) {
System.out.print(rs.getObject(i));
}
System.out.println(
"");
}
System.out.println(
"============================");
} catch (SQLException e) {
e.printStackTrace();
} finally {
//close resources
}
}
源码分析
在Statement和ResultSet接口中都有setFetchSize方法。
默认情况下pgjdbc driver会一次性拉取所有结果集,也就是在executeQuery的时候。对于大数据量的查询来说,非常容易造成OOM。这种场景就需要设置fetchSize,执行query的时候先返回第一批数据,之后next完一批数据之后再去拉取下一批。
- <span style="color: rgba(0, 0, 255, 1)">void</span> setFetchSize(<span style="color: rgba(0, 0, 255, 1)">int</span> rows) throws SQLException
- 使用要求
> 数据库必须使用V3协议,即pg7.4+
> connection的autoCommit必须为false,因为开启autoCommit的话,查询完成cursor会被关闭,那么下次就不能再fetch了。另外ResultSet必须是ResultSet.TYPE_FORWARD_ONLY类型,这个是默认的。也就是说无法向后滚动。
> 查询语句必须是单条,不能是用分号组成的多条查询。
- AP文档解析
Statement接口中是这样解释的:
为JDBC 驱动程序提供一个提示,它提示此Statement 生成的ResultSet 对象需要更多行时应该从数据库获取的行数。指定的行数仅影响使用此语句创建的结果集合。如果指定的值为 0,则忽略该提示。默认值为 0。
ResultSet中是这样解释的:
为 JDBC 驱动程序设置此ResultSet 对象需要更多行时应该从数据库获取的行数。如果指定的获取大小为零,则 JDBC 驱动程序忽略该值,随意对获取大小作出它自己的最佳猜测。默认值由创建结果集的Statement 对象设置。获取大小可以在任何时间更改。
setFetchSize 最主要是为了减少网络交互次数设计的。访问ResultSet时,如果它每次只从服务器上取一行数据,则会产生大量的开销。setFetchSize的意 思是当调用rs.next时,ResultSet会一次性从服务器上取得多少行数据回来,这样在下次rs.next时,它可以直接从内存中获取出数据而不 需要网络交互,提高了效率。 这个设置可能会被某些JDBC驱动忽略的,而且设置过大也会造成内存的上升。
数据库 - 连接配置引起的OOM
标签:i++ font rgba 提高 网络交互 连接池 拉取 行数据 语句