“结果集内存溢出”一般出现在一次从数据库查出了太多数据,直接放到内存里撑爆了 JVM。下面按常见场景 + 对应解决方案给你一个实用清单,你可以对照看看属于哪一种。
SELECT * FROM big_table;
数据库层分页
SELECT * FROM table
ORDER BY id
LIMIT 1000 OFFSET 0;
✅ 优点:简单、通用
❌ 缺点:OFFSET 大时性能差
PreparedStatement ps = conn.prepareStatement(
"SELECT * FROM big_table",
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY
);
ps.setFetchSize(Integer.MIN_VALUE); // 开启流式
✅ 一行一行读,几乎不占内存
✅ 适合大数据量导出、同步
SELECT * FROM table
WHERE id > ?
ORDER BY id
LIMIT 1000;
✅ 比 OFFSET 快
✅ 适合无限增长的数据
@Select("SELECT * FROM big_table")
@Options(fetchSize = Integer.MIN_VALUE)
void queryBigData(ResultHandler<T> handler);
或:
Cursor<T> cursor = sqlSession.selectCursor(statement);
for (T item : cursor) {
// 逐条处理
}
❌ 不推荐:
SELECT * FROM ...
✅ 推荐:
SELECT id, name, status FROM ...
❌ 错误示例:
List<Data> list = queryAll();
process(list);
✅ 正确:
while (hasNext) {
List<Data> list = queryNextPage();
process(list);
}
| 场景 | 方案 |
|---|---|
| Excel 导出 | SXSSFWorkbook(流式 Excel) |
| CSV | 边查边写 |
| 数据同步 | 游标 + MQ / 文件 |
-Xms4g -Xmx8g
⚠️ 只是临时方案,数据再大还是会炸
✅ 查询是否全表
✅ 是否分页
✅ 是否开启了流式 / 游标
✅ 是否一次加载到 List
✅ 是否有大字段
你可以直接贴:
我可以给你针对你代码的改法。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。