内存控制关键在于分批读取、及时刷新和合理缓冲区大小:需流式/分页读取ResultSet防全量加载,每写入千行flush一次,慎调BufferedWriter缓冲大小,并及时关闭资源。

用 BufferedWriter 批量写数据库数据到文件时,内存控制的关键不是 BufferedWriter 本身,而是**分批读取 + 及时刷新 + 合理缓冲区大小**。BufferedWriter 默认 8KB 缓冲,它不缓存数据行,只缓存字符数组;真正吃内存的是 ResultSet 遍历过程中的 JDBC 驱动行为(比如 MySQL 的 useCursorFetch=true)和 Java 端的对象持有。
分页/流式读取 ResultSet,避免全量加载
不要一次性 executeQuery() 后把几百万行全拉进 JVM。应启用流式游标或分页查询:
- MySQL:设置
statement.setFetchSize(Integer.MIN_VALUE)并开启useCursorFetch=true参数,让 ResultSet 按需从服务端拉数据 - PostgreSQL:默认支持流式,配合
setFetchSize(1000)即可(值不宜过大,100–5000 间较稳) - Oracle:用
setFetchSize()+setRowPrefetch()控制客户端缓存行数 - 通用替代方案:用 LIMIT/OFFSET 或游标分页(如
WHERE id > ? ORDER BY id LIMIT 1000),每次只查一批
写入时及时 flush,避免缓冲区累积
BufferedWriter 的缓冲区虽小,但若写入频率低、单次写入内容大(如每行含长 JSON),仍可能积压。建议:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 每写入 N 行(如 1000 行)调用一次
writer.flush(),释放底层 char[] 缓冲 - 避免在循环内频繁调用
write()+newLine()后不 flush;尤其当 NIO Path 写入或重定向到慢速设备时 - 不用
close()替代 flush——close 会 flush,但只应在最后调用;中途必须 flush 防止 OOM
控制 BufferedWriter 缓冲区大小与对象生命周期
默认 8KB 足够,但极端场景可微调:
立即学习“Java免费学习笔记(深入)”;
- 构造时指定缓冲区:
new BufferedWriter(new FileWriter(file), 64 * 1024)(64KB),适合高吞吐、IO 较快环境;但过大反而增加 GC 压力 - 务必在 finally 或 try-with-resources 中 close,防止资源泄漏导致缓冲区无法释放
- 不要长期持有 BufferedWriter 实例跨多批次——每批数据用新 writer 或复用时确保前一批已 flush/close
配套 JVM 与编码优化
Java 层面辅助降内存:
- ResultSet 处理完立刻
rs.close(),Statement 也及时关闭,释放 JDBC 内部缓冲 - 写入字符串尽量复用 StringBuilder 拼接,避免 String 相加产生临时对象
- JVM 加
-XX:+UseG1GC和合理堆设置(如-Xmx2g),避免 Full GC 频繁 - 考虑用
Files.newBufferedWriter()(NIO.2),底层更轻量,且支持 StandardOpenOption.APPEND

















