1、在微服务的yml中已配置 url: jdbc:postgresql://${db_ip}:${db_port}/${db_name}?useCursorFetch=true&defaultFetchSize=10000,意思是在获取到的ResultSet按游标滚动,每次取10000条记录,避免占用应用内存过大,导致OOM。实测结果仍为JDBC一次性取出全部200万记录。
2、查阅https://jdbc.postgresql.org/documentation/head/connect.html#connection-parameters发现参数为defaultRowFetchSize,修改为url: jdbc:postgresql://${db_ip}:${db_port}/${db_name}?useCursorFetch=true&defaultRowFetchSize=10000,仍然是一次取出全部记录。
3、在代码中将Statement stmt.setFetchSize(10000),仍然是一次取出全部记录。
4、将connection的autoCommit设置为false,Statement 设为仅向前滚动,每次取出10000条,执行完成再connection设回autoCommit=true,问题解决。每次只取10000条,达到节省内存的目的。
connection.setAutoCommit(false);
Statement stmt = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.FETCH_FORWARD);
stmt.setFetchSize(10000);
ResultSet rs = stmt.executeQuery(sql);
connection.setAutoCommit(true);
本文适用于数据查询返回记录数多,并发查询多,但微服务内存有限制的应用。