温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

结果集内存溢出咋办

发布时间:2026-07-15 15:10:12 来源:亿速云 阅读:89 作者:小樊 栏目:数据库

“结果集内存溢出”一般出现在一次从数据库查出了太多数据,直接放到内存里撑爆了 JVM。下面按常见场景 + 对应解决方案给你一个实用清单,你可以对照看看属于哪一种。


一、常见原因

  1. 一次性查询数据量太大
    SELECT * FROM big_table;
    
  2. 分页没做 / 分页参数失效
  3. 结果集直接放到 List / Map 里
  4. 流式/游标没开,JDBC 默认把结果全加载到内存
  5. 大字段(BLOB / CLOB / TEXT)一次性加载

二、解决方案(按推荐顺序)

✅ 1. 分页查询(最常用)

数据库层分页

SELECT * FROM table
ORDER BY id
LIMIT 1000 OFFSET 0;

✅ 优点:简单、通用
❌ 缺点:OFFSET 大时性能差


✅ 2. 游标 / 流式查询(强烈推荐)

MySQL(JDBC 流式)

PreparedStatement ps = conn.prepareStatement(
    "SELECT * FROM big_table",
    ResultSet.TYPE_FORWARD_ONLY,
    ResultSet.CONCUR_READ_ONLY
);
ps.setFetchSize(Integer.MIN_VALUE); // 开启流式

✅ 一行一行读,几乎不占内存
✅ 适合大数据量导出、同步


✅ 3. ID 游标分页(性能最好)

SELECT * FROM table
WHERE id > ?
ORDER BY id
LIMIT 1000;

✅ 比 OFFSET 快
✅ 适合无限增长的数据


✅ 4. MyBatis 流式查询

@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) {
    // 逐条处理
}

✅ 5. 只查需要的字段(减少内存)

❌ 不推荐:

SELECT * FROM ...

✅ 推荐:

SELECT id, name, status FROM ...

✅ 6. 异步 / 分批处理

  • 边查边处理
  • 不要先组装一个超大 List 再处理

❌ 错误示例:

List<Data> list = queryAll();
process(list);

✅ 正确:

while (hasNext) {
    List<Data> list = queryNextPage();
    process(list);
}

三、如果是大数据导出

场景 方案
Excel 导出 SXSSFWorkbook(流式 Excel)
CSV 边查边写
数据同步 游标 + MQ / 文件

四、JVM 层面(治标不治本)

  • 增大 JVM 内存(不推荐长期使用)
-Xms4g -Xmx8g

⚠️ 只是临时方案,数据再大还是会炸


五、快速排查 checklist

✅ 查询是否全表
✅ 是否分页
✅ 是否开启了流式 / 游标
✅ 是否一次加载到 List
✅ 是否有大字段


六、我可以进一步帮你

你可以直接贴:

  • 数据库类型(MySQL / Oracle / PG)
  • ORM(MyBatis / JPA / JDBC)
  • 报错信息
  • 使用场景(导出 / 同步 / 查询)

我可以给你针对你代码的改法

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI