MyBatis 在大数据量下使用流式查询进行数据同步
通常的数据同步中,如果数据量比较少的话可以直接全量同步,默认情况下,完整的检索结果集会将其存储在内存中。在大多数情况下,这是最有效的操作方式,并且由于 MySQL 网络协议的设计,因此更易于实现。但是如果数据量很大的话,全量同步需要大量的内存,如果内存不足的话则可能会导致内存溢出。
通常的会采用分页的方式,一批一批的同步,大体的实现方式如下:
``
```java
int page = 1;
int pageNum = 1000;
while (true){
UserQueryRequest request = new UserQueryRequest();
request.setPage(page);
request.setPageSize(pageNum);
PageInfo<User> pageInfo = userMapper.getUserPage(request);
if (CollectionUtils.isEmpty(pageInfo.getList()) ){
break;
}
List<User> userList = pageInfo.getList();
// 具体的处理逻辑 省略
page ++;
}
```
这种实现方式虽然可以实现分批同步,但是同步的数据必须先提供实现分页的查询方式,如果数据源是通过复杂的连表查询来的,先实现一个分页查询更是会增加实现的复杂度。解决这个问题可以使用一种更为优雅的解决方式,即使用流失查询。
流式查询,会建立长连接,利用服务端游标,每次读取一条加载到 JVM 内存,因此不会导致内存溢出。
## MyBatis 如何使用流式查询:
### 配置mapper.xml文件:
```xml
<select id="selectUsers" resultType="User" fetchSize="1000">
SELECT userId from t_user
</select>
```
### 自定义一个ResultHandler:
User是自定义的同步对象的实体对象,需要自己定义
```java
import lombok.extern.slf4j.Slf4j;
import model.User;
import org.apache.ibatis.session.ResultContext;
import org.apache.ibatis.session.ResultHandler;
import java.util.ArrayList;
import java.util.List;
/**
* @author: jie
* @create: 2023/3/29 16:51
* @description:
*/
@Slf4j
public class SyncDataHandler implements ResultHandler<User> {
/**
* 每批处理数量
*/
private final static int BATCH_SIZE = 1000;
/**
* 缓存数据
*/
private List<User> cacheList = new ArrayList<>();
/**
* 同步熟虑
*/
private int total = 0;
@Override
public void handleResult(ResultContext<? extends User> resultContext) {
User coreInfoCyDTO = resultContext.getResultObject();
this.cacheList.add(coreInfoCyDTO);
//每到达BATCH_SIZE 条数据处理一次
if (this.cacheList.size() >= BATCH_SIZE) {
this.handle();
}
total++;
}
/**
* 处理缓存数据
*/
private void handle() {
try {
// 具体的处理逻辑 省略
} finally {
// 清除处理过的缓存数据
this.cacheList.clear();
}
}
/**
* 处理最后一批没有进行处理的数据
*/
public int end() {
this.end();
return total;
}
}
```
### 使用代码示例:
```java
SyncDataHandler syncDataHandler = new SyncDataHandler();
userMapper.getUserList("selectUsers", syncDataHandler);
syncDataHandler.end();
```
## **结言**
流式查询可以避免 OOM,,数据量大可以考虑此方案,其占用内存大小取决于批处理大小**BATCH_SIZE**的设置。所以**BATCH_SIZE**应该根据业务情况设置合适的大小。但是这这种方式会占用数据库连接,使用中不会释放,所以线上针对大数据量业务用到流式操作,一定要进行并发控制。
MyBatis 在大数据量下使用流式查询进行数据同步的更多相关文章
- Mysql中使用JDBC流式查询避免数据量过大导致OOM
一.前言 java 中MySQL JDBC 封装了流式查询操作,通过设置几个参数,就可以避免一次返回数据过大导致 OOM. 二.如何使用 2.1 之前查询 public void selectData ...
- c#中@标志的作用 C#通过序列化实现深表复制 细说并发编程-TPL 大数据量下DataTable To List效率对比 【转载】C#工具类:实现文件操作File的工具类 异步多线程 Async .net 多线程 Thread ThreadPool Task .Net 反射学习
c#中@标志的作用 参考微软官方文档-特殊字符@,地址 https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/toke ...
- 大数据量查询容易OOM?试试MySQL流式查询
一.前言 程序访问 MySQL 数据库时,当查询出来的数据量特别大时,数据库驱动把加载到的数据全部加载到内存里,就有可能会导致内存溢出(OOM). 其实在 MySQL 数据库中提供了流式查询,允许把符 ...
- 大数据量下,分页的解决办法,bubuko.com分享,快乐人生
大数据量,比如10万以上的数据,数据库在5G以上,单表5G以上等.大数据分页时需要考虑的问题更多. 比如信息表,单表数据100W以上. 分页如果在1秒以上,在页面上的体验将是很糟糕的. 优化思路: 1 ...
- 达观数据CTO纪达麒:小标注数据量下自然语言处理实战经验
自然语言处理在文本信息抽取.自动审校.智能问答.情感分析等场景下都有非常多的实际应用需求,在人工智能领域里有极为广泛的应用场景.然而在实际工程应用中,最经常面临的挑战是我们往往很难有大量高质量的标注语 ...
- 实现 MyBatis 流式查询的方法
基本概念流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果.流式查询的好处是能够降低内存使用.如果没有流式查询,我们想要从数据库取 1000 万条记录而又没有足 ...
- MyBatis 如何实现流式查询
基本概念 流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果.流式查询的好处是能够降低内存使用. 如果没有流式查询,我们想要从数据库取 1000 万条记录而又没 ...
- MyBatis 流式查询
流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果.流式查询的好处是能够降低内存使用. 流式查询的过程当中,数据库连接是保持打开状态的,因此要注意的是:执行一个 ...
- Spark SQL - 对大规模的结构化数据进行批处理和流式处理
Spark SQL - 对大规模的结构化数据进行批处理和流式处理 大体翻译自:https://jaceklaskowski.gitbooks.io/mastering-apache-spark/con ...
- 浅谈PageHelper插件分页实现原理及大数据量下SQL查询效率问题解决
前因:项目一直使用的是PageHelper实现分页功能,项目前期数据量较少一直没有什么问题.随着业务扩增,数据库扩增PageHelper出现了明显的性能问题.几十万甚至上百万的单表数据查询性能缓慢,需 ...
随机推荐
- FastJson参数
名称 含义 备注 QuoteFieldNames 输出key时是否使用双引号,默认为true UseSingleQuotes 使用单引号而不是双引号,默认为false WriteMapNull ...
- el与data的两种写法
el的两种写法 Vue初始化(被创建)后会判断有无el 有el:创建Vue实例对象的时候配置el属性 无el:通过vm.$mount('#root')指定el的值 data的两种写法 对象式:data ...
- 《深入理解高并发编程:JDK核心技术》-冰河新书上市
大家好,我是冰河~~ 废话说多了没用,并发编程技术一直是初级程序员进阶高级工程师的前提条件,也是成为大厂程序员的必备技能,更是突破自身技术瓶颈的必经之路. 2022年6月我出版了"冰河技术丛 ...
- salesforce零基础学习(一百一十六)workflow -> flow浅谈
本篇参考: https://help.salesforce.com/s/articleView?id=sf.migrate_to_flow_tool_considerations_workflow.h ...
- NodeJS 实战系列:个人开发者应该如何选购云服务
这文章至少值一千元,因为这是我保守估计花出去的冤枉钱(请自行脑补一个苦笑的 emoji) 文章中会穿插选择云服务的一些建议,当然也会提供一些"薅羊毛"的技巧.不过在此之前我们要想清 ...
- CSS3新增选择器(属性选择器、结构伪类选择器、伪元素选择器)
本博文介绍CSS3中新增的选择器,包括属性选择器.结构伪类选择器和伪元素选择器. 1 属性选择器 属性选择器([属性])可以根据元素的属性和属性值来对符合要求的元素进行选择. 属性选择器的基础语法如 ...
- easy-excel读取远程地址获得文件进行上传
背景 作为一个快五年的程序员,一直以来还没有自己维护过自己的技术栈,最近也是有时间,所以也是下定决心,从头开始,一步一步的夯基础.最近在系统化的学习easy-excel,今天遇到了一个问题,特意记录一 ...
- day3 函数的定义和调用,练习编写简单的程序(记录1)
一.函数的定义 可以分为以下两种: 1.函数声明和函数定义分离 这种方法将函数声明和函数定义分开,通常在头文件中先声明函数原型,然后在源文件中实现函数定义. 例如,头文件 example.h 中声明了 ...
- [ElasticSearch]#Search Guard#sgadmin参数说明
sgadmin.sh/sgadmin.bat是Elastic Search的开源安全组件Search Guard内的可执行脚本. 在修改SG组件的用户角色.权限.密码时,需使用到此脚本. 在修改完Se ...
- [Linux]scp/sshpass:物理主机与虚拟机的文件传输
最初写这篇文章的时候,对 openssh大家族的工具套件(例如: ssh.sshd.ssl.scp等)不太熟悉,现在看来这个文章的标题(虚拟机与物理机)是存在问题的. 本质上,本文关心的并不是[虚拟机 ...