当前位置: 首页 > 知识库问答 >
问题:

java - MybatisPlus查询百万数据的内存占用问题?

宋志学
2023-11-06

我在表里添加了500W的测试数据,表中数据如下
image.png
一次性读取 500w 数据到 JVM 内存中 必然会造成OOM现象,所以我分别试验了2个读取百万数据的方式,并用Junit分析内存占用

  1. 分页多次查询,并进行深度分页优化
  @Test    void testPage(){        //查询出表中总记录数        Long total = orderMapper.selectCount(null);        //每次分页读取的结果数        int fetchSize = 100000;        // 分页优化参数,上次查询的最大ID        int lastMaxId = 0;        for (int i = 0; i < (total / fetchSize) + 1; i++) {            LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();            orderLambdaQueryWrapper.gt(Order::getOrderId, lastMaxId);            List<Order> records = orderMapper.selectPage(new Page<>(1, fetchSize), orderLambdaQueryWrapper).getRecords();           records.stream().forEach(System.out::println);            //获取本次最大的Id            lastMaxId = records.get(records.size() - 1).getOrderId();        }    }

image.png

  1. Mybatis的流式查询
  @Test    void testStream() {        orderMapper.selectList(Wrappers.emptyWrapper(), resultContext -> {            // 依次得到每条业务记录            System.out.println("当前处理第" + resultContext.getResultCount() + "条记录.");            Object order = resultContext.getResultObject();            System.out.println(order);            //做自己的业务处理,比如分发任务        });    }

image.png

我从网上看了许多博客,说流式查询可以很好避免OOM问题。
但是为什么在分析堆内存占用中,反而是 多次分页查询的内存占用更小,平均只有400MB
而流式查询却能高达平均1GB的占用?

关于如何开启流式查询是参考的MybatisPlus官网,MybatisPlus版本是也最新的。 https://baomidou.com/pages/1922u2/

共有1个答案

唐高卓
2023-11-06

多次分页查询和流式查询都是处理大量数据的常用策略。它们的工作原理和内存占用情况有所不同。

  1. 多次分页查询:这种策略是按照分页的方式逐步获取数据,每次只读取一小部分数据到内存中,因此它对内存的占用相对较小。在你的测试中,每次读取的数据量约为10万条,所以内存占用约为400MB。
  2. 流式查询:这种策略是逐步读取数据,并对每条数据进行处理,而不是一次性将所有数据加载到内存中。因此,流式查询的内存占用通常比多次分页查询要小。然而,在你的测试中,流式查询的内存占用却比多次分页查询要高,这可能是因为流式查询在处理每条数据时都会创建一个新的对象,而这个对象的销毁时间比较长,导致内存占用较高。

另外,你提到你参考了MybatisPlus的官方文档开启流式查询,但是你没有提到具体的开启方式。流式查询是否开启成功以及是否正确使用,可能也会影响内存占用情况。建议你仔细检查你的代码以及流式查询的使用方式,确保你正确地使用了流式查询。

总的来说,对于处理大量数据,多次分页查询和流式查询都有各自的优点。你可以根据你的实际需求和系统资源情况来选择适合的策略。如果你的系统内存资源充足,并且你需要一次性处理大量数据,那么流式查询可能是一个更好的选择。如果你的系统内存资源有限,或者你只需要处理一部分数据,那么多次分页查询可能更适合你。

 类似资料:
  • 开启十个线程,每个线程都会去查询500W的数据。 单独一个线程,堆内存占用500M。 十个线程,堆内存占用最高也不过1400MB,为什么会这样呢?这些内存占用居然不会叠加的吗?

  • 我有N个愿望是ID。对于每一个ID,我都需要执行一个Runnable(即,我不关心返回值),并等待它们全部完成。每个Runnable的运行时间从几秒到几分钟不等,并行运行大约100个线程是安全的。 在我们当前的解决方案中,我们使用Executors.NewFixedThreadPool(),对每个ID调用submit(),然后对每个返回的Future调用get()。 代码工作得很好,而且非常简单,

  • 本文向大家介绍C#百万数据查询出现超时问题的解决方法,包括了C#百万数据查询出现超时问题的解决方法的使用技巧和注意事项,需要的朋友参考一下 本文较为详细的讲解了C#百万数据查询出现超时问题的解决方法,分享给大家供大家参考之用。具体方法如下: 很多时候我们用C#从百万数据中筛选一些信息时,经常会出现程序连接超时的错误,常见的错误有很多,例如: Timeout expired. The timeout

  • 本文向大家介绍java 使用ElasticSearch完成百万级数据查询附近的人功能,包括了java 使用ElasticSearch完成百万级数据查询附近的人功能的使用技巧和注意事项,需要的朋友参考一下 上一篇文章介绍了ElasticSearch使用Repository和ElasticSearchTemplate完成构建复杂查询条件,简单介绍了ElasticSearch使用地理位置的功能。 这一篇

  • 注意:我无法访问与此问题相关的源代码/数据库。这两个表位于不同的服务器上。 我在一家第三方公司工作,该公司的系统与我们自己的系统集成。他们有一个运行类似这样的查询; 它在

  • 问题内容: 我有一个MSSQL表存储,该存储在表中具有以下列: 有人可以帮我进行SQL查询,以产生占雇员总数(NumEmployees)30%的顶级商店(storeID)吗? 问题答案: WITH cte AS (SELECT storeid, numemployees, ( numemployees * 100 ) / SUM(numemployees) OVER (PARTITION BY 1