时间:2021-05-02
目录
程序访问MySQL数据库时,当查询出来的数据量特别大时,数据库驱动把加载到的数据全部加载到内存里,就有可能会导致内存溢出(OOM)。
其实在MySQL数据库中提供了流式查询,允许把符合条件的数据分批一部分一部分地加载到内存中,可以有效避免OOM;本文主要介绍如何使用流式查询并对比普通查询进行性能测试。
使用JDBC的PreparedStatement/Statement的setFetchSize方法设置为Integer.MIN_VALUE或者使用方法Statement.enableStreamingResults()可以实现流式查询,在执行ResultSet.next()方法时,会通过数据库连接一条一条的返回,这样也不会大量占用客户端的内存。
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 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个测试用例进行测试:
3.1. 测试大数据量普通查询
? 1 2 3 4 5 @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. 测试大数据量流式查询
? 1 2 3 4 5 @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. 测试小数据量普通查询
? 1 2 3 4 5 @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. 测试小数据量流式查询
? 1 2 3 4 5 @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
到此这篇关于MySQL中使用流式查询避免数据OOM的文章就介绍到这了,更多相关MySQL 流式查询内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!
原文链接:https://segmentfault.com/a/1190000038792484
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
基本概念流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果。流式查询的好处是能够降低内存使用。如果没有流式查询,我们想要
在mysql中查询不区分大小写重复的数据,往往会用到子查询,并在子查询中使用upper函数来将条件转化为大写。如:复制代码代码如下:select*fromsta
说明:MariaDB是基于MySQL的开源数据库,兼容MySQL,现有的MySQL数据库可以迁移到MariaDB中使用MariaDB下载:32位:http://
以下是MySQL数据库的存储过程中使用WHILE循环语句: mysql> mysql>delimiter$$ mysql> mysql>CREATE
在项目中使用MyBatisPlus中的or()查询时由于误用,导致查询数据不对,仅作记录。写法一:LambdaQueryWrapperqueryWrapper=