【Java】项目中大批量数据查询导致OOM

这篇具有很好参考价值的文章主要介绍了【Java】项目中大批量数据查询导致OOM。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景

项目中有时候一次性将大批量数据都查出来到内存中导致内存占用过多很可能会导致内存溢出

内存溢出的具体原因

在JVM内存结构中分为以下几个模块

  • 程序计数器
  • 虚拟机栈
  • 本地方法栈
  • 堆内存
  • 方法区

程序中的实例对象包括从数据库读取的数据是存在堆内存中的。
所以这里的OutOfMemoryError是因为数据量过大超过了堆内存中设置的最大内存,一次性读取的数据太多导致内存容纳不下,抛出了内存异常

错误模拟

如果堆的内存大小超过 -Xmx 设定的最大内存, 就会抛出 OutOfMemoryError 异常,先准备好数据在启动项目时把堆内存的最大值设置小一点就可以进行模拟内存溢出的异常

搭建一个本地项目。需求描述:查询表call_task中待拨打的数据进行拨打,call_task中一次可能会有大批量数据需要处理。本次准备了1万条数据

/**
 * 查询数据执行拨打
 **/
@Override
public void waitingCall() {
    List<CallTask> waitingTaskList = list(Wrappers.<CallTask>lambdaQuery()
            .eq(CallTask::getCallStatus, "WAITING")
            .le(CallTask::getReqTime, new Date())
    );
    if (CollUtil.isEmpty(waitingTaskList)) {
        return;
    }

    call(waitingTaskList);
}

/**
 * 模拟执行具体拨打数据
 **/
private void call(List<CallTask> waitingTaskList) {
    try {
        TimeUnit.SECONDS.sleep(5);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
}

启动项目时将JVM堆内存的大小调整到合适数值(可以造成内存溢出的情况)。
本次最大设置的20m,最小设置的10m

  • -Xmx用来表示堆的最大内存
  • -Xms用来表示堆的最小内存

idea设置方式, 选择 run/debug configurations 设置 VM options
【Java】项目中大批量数据查询导致OOM

问题复现

启动程序执行方法,程序出现错误 java.lang.OutOfMemoryError: Java heap space
【Java】项目中大批量数据查询导致OOM

解决办法

既然是数据量过大导致的问题,我们可以减少每次查询的数据来解决这个问题

使用分页查询,避免一次性查询所有的数据,分批次处理

public void methodOne() {
    long page = 1;
    long limit = 500;
    long total;
    do {
        Page<CallTask> taskPage = new Page<>(page, limit);
        Page<CallTask> pagResult = page(taskPage,
                Wrappers.<CallTask>lambdaQuery()
                        .eq(CallTask::getCallStatus, "WAITING")
                        .le(CallTask::getReqTime, new Date()));
        total = pagResult.getTotal();

        List<CallTask> records = pagResult.getRecords();
        if (CollUtil.isEmpty(records)) {
            break;
        }
        call(records);
        page++;

    } while (page * limit < total);
}

使用流式查询

public void methodTwo() {
    Date reqDate = new Date();
    LambdaQueryWrapper<CallTask> wrapper = Wrappers.<CallTask>lambdaQuery()
            .eq(CallTask::getCallStatus, "WAITING")
            .le(CallTask::getReqTime, reqDate);
    int batchSize = 1000;
    int offset = 0;
    while (true) {
        List<CallTask> taskList = list(wrapper.last("limit " + offset + "," + batchSize));
        if (CollUtil.isEmpty(taskList)) {
            break;
        }
        offset += batchSize;
        call(taskList);
    }
}

流式查询和分页查询的使用场景

分页查询通常用于展示数据,如在网页上显示数据列表,需要分页展示。而流式查询通常用于数据处理,如在数据清洗、数据分析等场景中

查询数据的建议

减少查询字段,避免 select *文章来源地址https://www.toymoban.com/news/detail-488570.html

到了这里,关于【Java】项目中大批量数据查询导致OOM的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 解决数据库查询时间过长导致com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure

    大数据量下数据库查询中断,抛出异常,异常信息见附录1。 使用springboot项目测试分库分表,使用sharding-jdbc插件,2000w数据量查询总数count(*)查询,查询失败,经过排查,排除了sharding-jdbc插件的问题,还原原始的mybatis-plus查询方式依然报错,经过查阅网上的相关文章,尝试修

    2024年02月11日
    浏览(221)
  • 项目实战:ES的增加数据和查询数据

    项目实战:ES的增加数据和查询数据

    最近需要做一个有关查询聊天记录的功能,通过资料了解到使用ES可以方便我们快速查询内容。自己进行ES框架的搭建,感兴趣的可以看博客进行学习:https://blog.csdn.net/weixin_45309155/article/details/132686375?spm=1001.2014.3001.5501 ES搭建好之后就是应用了,下面就先总结一下关于最近在项

    2024年02月07日
    浏览(10)
  • 商城项目-es的海量查询/聚合/数据同步

    商城项目-es的海量查询/聚合/数据同步

    1.sql表 用户数据库: tb_user:用户表,其中包含用户的详细信息 tb_address:用户地址表 商品数据库 tb_item:商品表 订单数据库 tb_order:用户订单表 tb_order_detail:订单详情表,主要是订单中包含的商品信息 tb_order_logistics:订单物流表,订单的收货人信息 2.模块搭建 feign-api:是

    2024年01月21日
    浏览(11)
  • 前后端分离项目(六):数据分页查询(前端视图)

    前后端分离项目(六):数据分页查询(前端视图)

    🚀 优质资源分享 🚀 🧡 Python实战微信订餐小程序 🧡 进阶级 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。 💛Python量化交易实战💛 入门级 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统 好家伙,该项

    2024年02月07日
    浏览(44)
  • MyBatis查询数据库之一(概念+创建项目+基础交互)

    MyBatis查询数据库之一(概念+创建项目+基础交互)

    目录 1.MyBatis是什么? 2.为什么学习MyBatis? 3. 怎么学 MyBatis 4.第⼀个MyBatis查询 4.1 添加MyBatis框架支持 4.1.1老项目添加MyBatis 4.1.2 新项目添加MyBatis 4.2 配置连接字符串和MyBatis 4.2.1 配置连接字符串 4.2.2 配置 MyBatis 中的 XML 路径 5. 使用 MyBatis 的操作模式操作数据库 5.1 添加实体类

    2024年02月13日
    浏览(28)
  • 【Java】Mybatis查询数据库

    【Java】Mybatis查询数据库

    经过前面的学习Spring系列的操作已经差不多了,接下来我们继续学习更加重要的知识,将前端传递的参数存储起来,或者查询数据库里面的数据 MyBatis是款优秀的持久层框架,它支持自定义SQL、存储过程以及高级映射。MyBatis几乎祛除了所有的JDBC代码以及设置参数和获取结果集

    2024年01月18日
    浏览(31)
  • java查询数据库百万条数据,优化之:多线程+数据库

    java查询数据库百万条数据,优化之:多线程+数据库

    今天去面试时hr问了个关于大量数据查询的问题。 面试官:“我们公司是做数据分析的,每次需要从数据库中查询100万条数据进行分析,该接口不能用分页(不限制具体怎么实现),请问怎么优化sql或者java代码呢??” 如果用普通查询需要5分多分钟才查询完毕,所以我们用

    2024年02月15日
    浏览(11)
  • Java操作elasticSearch复杂查询以及解析数据以及索引保存数据

    Java操作elasticSearch复杂查询以及解析数据以及索引保存数据

    说明:基于银行测试库的操作 es的银行测试库,看一个Kibana操作 然后用java检索解析这个数据 聚合搜索 address 中包含 mill 的所有人的年龄分布以及平均薪资 以下是分解思路实现步骤: #聚合搜索 address 中包含 mill 的所有人的年龄分布以及平均年龄 GET bank/_search { “query”:{ “

    2024年02月10日
    浏览(14)
  • 【java爬虫】将优惠券数据存入数据库排序查询

    【java爬虫】将优惠券数据存入数据库排序查询

    本文是在之前两篇文章的基础上进行写作的 (1条消息) 【java爬虫】使用selenium爬取优惠券_haohulala的博客-CSDN博客 (1条消息) 【java爬虫】使用selenium获取某宝联盟淘口令_haohulala的博客-CSDN博客  前两篇文章介绍了如何获取优惠券的基础信息,本文将获取到的基本信息存到数据库中

    2024年02月16日
    浏览(14)
  • Java查询es数据,根据指定id检索(in查询),sql权限过滤,多字段匹配检索,数据排序

    Java集成Elasticsearch,进行索引数据查询,并进行sql权限过滤,指定id检索(in查询),多字段匹配检索,数据排序。由于权限过滤是根据sql语句判断当前用户或其部门可查询的数据,所以采用以下方法: 1.通过sql过滤出当前用户可查询的数据id集合idsList; 2.将当前用户可查询的

    2024年02月22日
    浏览(12)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包