通常的数据同步中,如果数据量比较少的话可以直接全量同步,默认情况下,完整的检索结果集会将其存储在内存中。在大多数情况下,这是最有效的操作方式,并且由于 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 在大数据量下使用流式查询进行数据同步的更多相关文章

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

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

  2. 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 ...

  3. 大数据量查询容易OOM?试试MySQL流式查询

    一.前言 程序访问 MySQL 数据库时,当查询出来的数据量特别大时,数据库驱动把加载到的数据全部加载到内存里,就有可能会导致内存溢出(OOM). 其实在 MySQL 数据库中提供了流式查询,允许把符 ...

  4. 大数据量下,分页的解决办法,bubuko.com分享,快乐人生

    大数据量,比如10万以上的数据,数据库在5G以上,单表5G以上等.大数据分页时需要考虑的问题更多. 比如信息表,单表数据100W以上. 分页如果在1秒以上,在页面上的体验将是很糟糕的. 优化思路: 1 ...

  5. 达观数据CTO纪达麒:小标注数据量下自然语言处理实战经验

    自然语言处理在文本信息抽取.自动审校.智能问答.情感分析等场景下都有非常多的实际应用需求,在人工智能领域里有极为广泛的应用场景.然而在实际工程应用中,最经常面临的挑战是我们往往很难有大量高质量的标注语 ...

  6. 实现 MyBatis 流式查询的方法

    基本概念流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果.流式查询的好处是能够降低内存使用.如果没有流式查询,我们想要从数据库取 1000 万条记录而又没有足 ...

  7. MyBatis 如何实现流式查询

    基本概念 流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果.流式查询的好处是能够降低内存使用. 如果没有流式查询,我们想要从数据库取 1000 万条记录而又没 ...

  8. MyBatis 流式查询

    流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果.流式查询的好处是能够降低内存使用. 流式查询的过程当中,数据库连接是保持打开状态的,因此要注意的是:执行一个 ...

  9. Spark SQL - 对大规模的结构化数据进行批处理和流式处理

    Spark SQL - 对大规模的结构化数据进行批处理和流式处理 大体翻译自:https://jaceklaskowski.gitbooks.io/mastering-apache-spark/con ...

  10. 浅谈PageHelper插件分页实现原理及大数据量下SQL查询效率问题解决

    前因:项目一直使用的是PageHelper实现分页功能,项目前期数据量较少一直没有什么问题.随着业务扩增,数据库扩增PageHelper出现了明显的性能问题.几十万甚至上百万的单表数据查询性能缓慢,需 ...

随机推荐

  1. vulnhub靶场之HACKSUDO: SEARCH

    准备: 攻击机:虚拟机kali.本机win10. 靶机:hacksudo: search,下载地址:https://download.vulnhub.com/hacksudo/hacksudo-sea ...

  2. Spring IOC——源码分析

    Spring 容器的 refresh() 创建容器 1 //下面每一个方法都会单独提出来进行分析 2 @Override 3 public void refresh() throws BeansExc ...

  3. IP代理的使用 IP代理爬取视频

    IP代理的使用 IP代理的分类 透明代理:目标网址知道你使用了代理并且知道你的源IP地址 匿名代理:匿名程序比较低 也就是网站知道你使用代理 但是查不出来源IP地址 高匿代理:网站不知道你使用了代理 ...

  4. Java 内存模型(二)

    Java 内存模型(二) happens-before ​ JSR-133 提出了 happens-before 的概念,通过这个概念来阐述操作之间的内存可见性.如果一个操作执行的结果需要对另一个操作 ...

  5. Linux 大文件按大小切割,合并还原

                    工作中,由于堡垒机限制,大文件无法上传,故产生切割大文件上传后合并还原的需求. 不说废话,直接上干货: 切割: 1.1G文件,切割为200M大小的几个文件: split ...

  6. 使用 Azure OpenAI 打造自己的 ChatGPT

    一.前言 当今的人工智能技术正在不断发展,越来越多的企业和个人开始探索人工智能在各个领域中的应用.其中,在自然语言处理领域,OpenAI 的 GPT 系列模型成为了研究热点.OpenAI 公司的 Ch ...

  7. selenuim文件的下载

    文件下载:谷歌浏览器则会自动实现下载,不会弹出框提示,会直接下载谷歌的默认路径:火狐浏览器下载会弹出提示框,此时火狐需要添加浏览器的配置参数信息: 火狐的相关浏览器配置参数可以通过about:conf ...

  8. HaProxy 安装搭建配置

    HaProxy简介 HAProxy是一个免费的负载均衡软件,可以运行于大部分主流的Linux操作系统上. HAProxy提供了L4(TCP)和L7(HTTP)两种负载均衡能力,具备丰富的功能.HAPr ...

  9. PySimpleGU之运行多个窗口

    这是PySimpleGUI继续简单的地方,但是问题空间刚刚进入了"复杂"领域. 如果您希望在事件循环中运行多个窗口,则有两种方法可以执行此操作. 当第二个窗口可见时,第一个窗口不会 ...

  10. [PKM]阅读的方法

    0 概述 数据 => 信息 => 知识 => 智慧 1 读书的目的 : 先寻求真理,而后实践 => 先博学,而后守约(读透) & 先泛读/速读,再精读 / 知行合一 年 ...