一、前言

程序访问 MySQL 数据库时,当查询出来的数据量特别大时,数据库驱动把加载到的数据全部加载到内存里,就有可能会导致内存溢出(OOM)。

其实在 MySQL 数据库中提供了流式查询,允许把符合条件的数据分批一部分一部分地加载到内存中,可以有效避免OOM;本文主要介绍如何使用流式查询并对比普通查询进行性能测试。

二、JDBC实现流式查询

使用JDBC的 PreparedStatement/StatementsetFetchSize 方法设置为 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个测试用例进行测试:

  1. 大数据量普通查询(27w条)
  2. 大数据量流式查询(27w条)
  3. 小数据量普通查询(10条)
  4. 小数据量流式查询(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

扫码关注有惊喜!

大数据量查询容易OOM?试试MySQL流式查询的更多相关文章

  1. DB2大数据量优化查询解决方案

    利用DB2表分区的功能对大数据量的表进行分区,可以优化查询. 表分区介绍: 表分区是一种数据组织方案,它根据一列或多列中的值把表数据划分为多个称为数据分区 的存储对象. (我觉得表分区就类似于Wind ...

  2. Mysql中使用JDBC流式查询避免数据量过大导致OOM

    一.前言 java 中MySQL JDBC 封装了流式查询操作,通过设置几个参数,就可以避免一次返回数据过大导致 OOM. 二.如何使用 2.1 之前查询 public void selectData ...

  3. mysql处理大数据量的查询速度究竟有多快和能优化到什么程度

    mysql处理大数据量的查询速度究竟有多快和能优化到什么程度 深圳-ftx(1433725026) 18:10:49  mysql有没有排名函数啊 横瓜(601069289) 18:13:06  无 ...

  4. MySQL大数据量分页查询

    mysql大数据量使用limit分页,随着页码的增大,查询效率越低下. 测试实验 1.   直接用limit start, count分页语句, 也是我程序中用的方法: select * from p ...

  5. 【1】MySQL大数据量分页查询方法及其优化

    ---方法1: 直接使用数据库提供的SQL语句---语句样式: MySQL中,可用如下方法: SELECT * FROM 表名称 LIMIT M,N---适应场景: 适用于数据量较少的情况(元组百/千 ...

  6. MySQL大数据量分页查询方法及其优化

    MySQL大数据量分页查询方法及其优化   ---方法1: 直接使用数据库提供的SQL语句---语句样式: MySQL中,可用如下方法: SELECT * FROM 表名称 LIMIT M,N---适 ...

  7. MySQL分页查询大数据量优化方法

    方法1: 直接使用数据库提供的SQL语句 语句样式: MySQL中,可用如下方法: SELECT * FROM 表名称 LIMIT M,N适应场景: 适用于数据量较少的情况(元组百/千级)原因/缺点: ...

  8. mysql的大数据量的查询

    mysql的大数据量查询分页应该用where 条件进行分页,limit 100000,100,mysql先查询100100数据量,查询完以后,将 这些100000数据量屏蔽去掉,用100的量,但是如果 ...

  9. 提高MYSQL大数据量查询的速度

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...

随机推荐

  1. HTTP协议数据包

    HTTP数据包 简介:由w3c制定的一种网络应用层协议,定义了浏览器与web服务器之间通信时所使用的数据格式. 0x00 数据包格式 1.请求行:请求类型/请求资源路径.协议的版本和类型 2.请求头: ...

  2. 自学linux——21. NFS服务器的搭建

    NFS服务器的搭建 1.NFS的认识 NFS(Network File System即网络文件系统)服务最大的功能就是可以透过网络,让不同的机器.不同的操作系统.可以彼此分享文件,可以将远程 Linu ...

  3. Leetcode学习笔记(4)

    题目1 ID121 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润. 注意你不能在买入股 ...

  4. ripple Failed to load resource: the server responded with a status of 404 (Not Found)

    在VS2015中使用Cordova + typescript开发中,遇到个问题. 在javascript console 中提示: Failed to load resource: the serve ...

  5. 个人作业三——ATM管理系统

    一 作业信息 博客班级 https://edu.cnblogs.com/campus/ahgc/AHPU-se-JSJ18/ 作业要求 https://edu.cnblogs.com/campus/a ...

  6. Robot Framework+adb框架自动化测试Android设备案例⑸——L1层测试用例

    一.L1层测试用例 1.初始化.robot *** Settings *** Resource ../L2层关键字.robot *** Test Cases *** 切换EMMC模式 [Tags] A ...

  7. Oracle 迁移数据库到 mysql

    一. oracle导出.sql文件(Navicat Premiu  11.0.8  无法实现oracle到mysql的数据传输亲测有效) exp username/pass@数据局地址ip:1521/ ...

  8. Spring AOP的理解(通俗易懂)。

    转载 原文链接:http://www.verydemo.com/demo_c143_i20837.html 这种在运行时,动态地将代码切入到类的指定方法.指定位置上的编程思想就是面向切面的编程. 1. ...

  9. 写一个为await自动加上catch的loader逐渐了解AST以及babel

    为什么要写这个loader 我们在日常开发中经常用到async await去请求接口,解决异步.可async await语法的缺点就是若await后的Promise抛出错误不能捕获,整段代码区就会卡住 ...

  10. 【Go语言绘图】图片的旋转

    在上一篇中,我们了解了gg库的基本使用,包括调整大小.调整圆形参数.设置颜色.保存图片.加载图片和裁剪.这一篇我们来学习一下图片的旋转. 加载图片 首先,我们先来一张黄图. func TestRota ...