查看原文
其他

MySQL中如何使用流式查询避免数据量过大导致OOM?

加多 根哥啊 2022-04-29

作者:加多

来源:www.jianshu.com/p/c1e6eeb71c74

一、前言

MySQL 是目前使用比较广泛的关系型数据库,而从数据库里面根据条件查询数据到内存的情况想必大家在日常项目实践中都有使用。

当指定条件的数据量特别大时候一般是通过分页的方式在前端页面通过 Tag 标签一页页的加载数据到内存;但是有些情况下却不需要用户切换 Tag 标签的方式一页页的加载数据,这时候如果一下子全部把数据加载内存,就有可能会导致 OOM,虽然这时候可以通过程序控制分页查询,但是每次查询时候数据库都需要把所有符合条件的数据查询出来然后根据当前页的返回来返回指定的页,这无疑加重了 MySQL 服务器不必要的开销。

其实在 MySQL 中提供了流式查询,这允许把符合条件的数据一部分一部分的加载到内存,本 Chat 就来具体讲解如何在 MySQL中使用流式查询:

使用流式查询前,我们是如何在 MySQL 中进行查询数据的,整个过程发生了什么?

如何使用 JDBC 编程方式在 MySQL 中使用流式查询?

二、普通查询

- 当我们在JVM进程里面的某一个线程里面执行数据库查询时候,其实这个请求首先会调用mysql驱动程序。 

- mysql驱动接受到请求后会向MySQL服务器发起TCP请求,服务器端根据条件查询出匹配的数据,然后通过TCP链接发送到MySQL驱动 

- MySQL驱动内则会把符合条件的数据缓存到驱动内,等服务器返回了所有符合条件的数据后,在一下子把缓存里面的数据返回给调用sql的应用程序。

所以如果查询的数据量特别大,那么mysql驱动内缓存就可能把内存撑爆造成OOM。

三、JDBC编程中MySQL流式查询

mysql客户端流式查询不会一下子把服务器端所有数据缓存起来,而是一部分一部分的把服务器端返回的数据返回给应用程序层,所以可以有效避免OOM。

1、之前查询

2、现在流式查询

可知只是prepareStatement时候改变了参数,并且设置了PreparedStatement的fetchsize为Integer.MIN_VALUE。

四、结果对比

对于同一个sqlCmd,同一批数据,使用两种方式占用内存对比如下:

1、非流式编程

2、流式编程

另外非流式方式由于是把符合条件的数据一下子全部加在到内存,并且由于数据量比较大,需要mysql处理的时间比较长,我测试情况下需要一分钟才会返回结果到内存(数据量比较大),然后才能通过数据集返回数据。

而流式方式是每次返回一个记录到内存,所以占用内存开销比较小,并且调用后会马上可以访问数据集的数据。

最近热文阅读:

1、从程序员的角度深入理解MySQL!

2、对Java意义重大的7个性能指标!

3、为什么不推荐数据库使用外键约束?

4、一个线程OOM,进程里其他线程还能运行么?

5、老板喊你设计一个秒杀系统!

6、牛逼哄哄的 RPC 框架,底层到底什么原理?

7、StackOverflow: 你没见过的七个最好的Java答案!

关注公众号,你想要的Java都在这里!

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存