首页 > 其他分享 >MyBatis 在大数据量下使用流式查询进行数据同步

MyBatis 在大数据量下使用流式查询进行数据同步

时间:2023-05-19 23:46:33浏览次数:39  
标签:同步 流式 查询 数据量 MyBatis import SIZE

通常的数据同步中,如果数据量比较少的话可以直接全量同步,默认情况下,完整的检索结果集会将其存储在内存中。在大多数情况下,这是最有效的操作方式,并且由于 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,import,SIZE
From: https://www.cnblogs.com/fhey/p/17416597.html

相关文章

  • Mybatis框架1
    XML配置:MyBatis的配置文件包含了会深深影响Mybatis行为的设置和属性信息。配置文档的顶层结构如下:configuration(配置)properties(属性)settings(设置)typeAliases(类型别名)typeHandlers(类型处理器)objectFactory(对象工厂)plugins(插件)enviroment(环境配置)environment(环境变量)transactionMa......
  • mybatis plus实体类中字段映射mysql中的json格式方式
    packagecom.example.springbootstudy.entity;importcom.baomidou.mybatisplus.annotation.TableField;importcom.baomidou.mybatisplus.annotation.TableId;importcom.baomidou.mybatisplus.annotation.TableName;importcom.baomidou.mybatisplus.extension.handlers.Fas......
  • 分享一下mybatisPlus新代码生成器3.5.1以上
    pom引入:有MP了就不要再引入mybatis了,会出bug的<!--mybatis-plus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.1</......
  • Mybatis查询
    查询查询的数据为单条实体类使用实体类进行接受即可,或者使用list,map接口均可.后面两者比较浪费使用实体类接受mapper接口:UserselectUserById(intuserid);映射文件:使用实体类<!--第二个一致,对应方法名UserselectUserById(intuserid);--><selec......
  • 老杜MyBatis框架从入门到精通(三)使用MyBatis完成CRUD
    mybatis做为目前国内最为流行的开源orm框架,我们平时在使用时会感受到其带来的诸多便利,但是很少去深入分析,mybatis源码代码量不多,功能丰富,是一个很好的学习样例,本系列文章就和大家一起来学习mybatis框架本系列笔记根据动力节点B站上老杜讲的mybatis教程整理~学习地址:https://www......
  • Mybatis和Mybatis-Plus对MySQL中json类型处理
    目录1MySQL中json类型处理1.1引言1.2准备建表1.3Mybatis1.3.1实体类1.3.2BaseTypeHandler1.3.3application.yml1.3.4修改SQL文件1.4MybatisPlus1.4.1实体类1.4.2application.yml1.4.3SQL文件1MySQL中json类型处理1.1引言mysql5.7开始支持json类型字段点击了解M......
  • 聊聊Mybatis集成Spring的原理
    一般都是研究框架源码,我为什么要反过来研究集成原理呢?在我自己看来,集成虽然比较简单,但要求的细节比较多,需要掌握根本性的东西才能做到集成。Mybatis集成Spring用到了FactoryBean以及BeanDefinition注册的原理,从这两个维度来实现集成,而我们单独学习Spring时,一般会忽略这两点。My......
  • MybatisPlus中LamdaQueryWrapper 与 QueryWrapper的使用及区别
    一、QueryWrapper的使用;比如有一张表trolley_itme,需要通过device_id查询出符合条件的所有数据(返回List集合);1、QueryWrapper的最基础的使用方式是这样的:必须写清楚具体的字段名称(即有硬编码的嫌疑)//查询条件的构造器:QueryWrapper<TrolleyItme>queryWrapper=new QueryWra......
  • SpringBoot02_Mybatis和配置文件
    关于本文的大体框架在上一篇博客一、SpringBoot整合Mybatis(一)配置文件​ 引入springboot与mybatis整合包以及java-connector<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><versi......
  • MyBatis 学习(二)
    一、XML配置文件1、XML映射配置文件的结构configuration配置properties属性settings设置typeAliases类型别名typeHandlers类型处理器objectFactory对象工厂plugins插件environments环境environment环境变量......