MySQL中使用流式查询避免数据OOM
作者:zlt2000 发布时间:2024-01-23 01:23:00
一、前言
程序访问MySQL
数据库时,当查询出来的数据量特别大时,数据库驱动把加载到的数据全部加载到内存里,就有可能会导致内存溢出(OOM)。
其实在MySQL
数据库中提供了流式查询,允许把符合条件的数据分批一部分一部分地加载到内存中,可以有效避免OOM;本文主要介绍如何使用流式查询并对比普通查询进行性能测试。
二、JDBC实现流式查询
使用JDBC的PreparedStatement/Statement
的setFetchSize
方法设置为Integer.MIN_VALUE
或者使用方法Statement.enableStreamingResults()
可以实现流式查询,在执行ResultSet.next()
方法时,会通过数据库连接一条一条的返回,这样也不会大量占用客户端的内存。
public int execute(String sql, boolean isStreamQuery) throws SQLException {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
int count = 0;
try {
//获取数据库连接
conn = getConnection();
if (isStreamQuery) {
//设置流式查询参数
stmt = conn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);
} else {
//普通查询
stmt = conn.prepareStatement(sql);
}
//执行查询获取结果
rs = stmt.executeQuery();
//遍历结果
while(rs.next()){
System.out.println(rs.getString(1));
count++;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
close(stmt, rs, conn);
}
return count;
}
「PS」:上面的例子中通过参数isStreamQuery
来切换「流式查询」与「普通查询」,用于下面做测试对比。
三、性能测试
创建了一张测试表my_test
进行测试,总数据量为27w
条,分别使用以下4个测试用例进行测试:
大数据量普通查询(27w条)
大数据量流式查询(27w条)
小数据量普通查询(10条)
小数据量流式查询(10条)
3.1. 测试大数据量普通查询
@Test
public void testCommonBigData() throws SQLException {
String sql = "select * from my_test";
testExecute(sql, false);
}
3.1.1. 查询耗时
27w 数据量用时 38 秒
3.1.2. 内存占用情况
使用将近 1G 内存
3.2. 测试大数据量流式查询
@Test
public void testStreamBigData() throws SQLException {
String sql = "select * from my_test";
testExecute(sql, true);
}
3.2.1. 查询耗时
27w 数据量用时 37 秒
3.2.2. 内存占用情况
由于是分批获取,所以内存在30-270m波动
3.3. 测试小数据量普通查询
@Test
public void testCommonSmallData() throws SQLException {
String sql = "select * from my_test limit 100000, 10";
testExecute(sql, false);
}
3.3.1. 查询耗时
10 条数据量用时 1 秒
3.4. 测试小数据量流式查询
@Test
public void testStreamSmallData() throws SQLException {
String sql = "select * from my_test limit 100000, 10";
testExecute(sql, true);
}
3.4.1. 查询耗时
10 条数据量用时 1 秒
四、总结
MySQL 流式查询对于内存占用方面的优化还是比较明显的,但是对于查询速度的影响较小,主要用于解决大数据量查询时的内存占用多的场景。
「DEMO地址」:https://github.com/zlt2000/mysql-stream-query
来源:https://segmentfault.com/a/1190000038792484
猜你喜欢
- 在Python 中有几种方法可以读取文本文件。在本文中,我将介绍 open() 函数、read() 方法、re
- 介绍Session:在计算机中,尤其是在网络应用中,称为“会话控制”。Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户
- 问:我最近升级了一个应用程序,使其可以在 SQL Server 2005 上运行。我利用了允许行长度超出 8,060 个字节这项功能,以便用
- 对于注入而言,错误提示是极其重要。所谓错误提示是指和正确页面不同的结果反馈,高手是很重视这个一点的,这对于注入点的精准判断至关重要。本问讨论
- tomorrow是我最近在用的一个爬虫利器,该模块属于第三方的一个模块,使用起来非常的方便,只需要用其中的threads方法作为装饰器去修饰
- DataList Web 服务器控件 通过使用模板显示数据源中的项。通过操作组成 DataList
- 目录1.Python语法错误2.Python运行时错误前言:开发人员在编写程序时,难免会遇到错误,有的是编写人员疏忽造成的语法错误,有的是程
- Python作为一种脚本语言,其要求强制缩进,使其易读、美观,它的数据类型可以实现自动转换,而不需要像C、Java那样给变量定义数据类型,使
- 1、用户有三种:活跃用户、沉睡用户、外部用户。2、据不完全统计,外部用户8亿,沉睡用户1.2亿,活跃用户1千万。3、就算不去管活跃用户,或者
- 前言提示:在管理服务器的过程中,发现有很多服务器在启动的过程中默认以PXE方式启动,这就导致我们无法将PXE装机程序放开到所有的交换机端口中
- 本文实例为大家分享了Python飞机大战项目,供大家参考,具体内容如下import gcimport randomimport pygame
- 最近工作转型到数据开发领域,想在本地搭建一个数据开发环境。自己有三年python开发经验,马上想到使用numpy、scipy、sklearn
- 常用当前循环.作用default数据为空时设置默认值length取变量长度filesizeformat文件大小转成可读slice从指定位置到
- 原来sql还有个stuff的函数,很强悍。 一个列的格式是单引号后面跟着4位的数字,比如'0003,'0120,'4
- 线性逻辑回归本文用代码实现怎么利用sklearn来进行线性逻辑回归的计算,下面先来看看用到的数据。这是有两行特征的数据,然后第三行是数据的标
- 在官方网站中对as_index有以下介绍:as_index : boolean, default TrueFor aggregated ou
- 前言我们把可能发生错误的语句放在try模块里,用except来处理异常。except可以处理一个专门的异常,也可以处理一组圆括号中的异常,如
- 我们经常会遇到数据库磁盘空间爆满的问题,或由于归档日志突增、或由于数据文件过多、大导致磁盘使用紧俏。这里主要说的场景是磁盘空间本身很大,但表
- 报“服务没有及时响应或控制请求”的错误,改用pyinstaller生成也是不行;查资料后修改setup.py如下即可,服务名、脚本名请自行替
- 译序:这篇文章是可用性大师 Jakob Nielsen 在10年前总结的,到今天仍然受用。通过这个时间跨度,可以得出,可用性话题不是某个时代