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

 更新时间:2023年05月30日 10:56:01   作者:知北游z  
通常的数据同步中,如果数据量比较少的话可以直接全量同步,但是如果数据量很大的话,全量同步需要大量的内存,所以本文为大家介绍了MyBatis使用流式查询实现数据同步的方法,希望对大家有所帮助

通常的数据同步中,如果数据量比较少的话可以直接全量同步,默认情况下,完整的检索结果集会将其存储在内存中。在大多数情况下,这是最有效的操作方式,并且由于 MySQL 网络协议的设计,因此更易于实现。但是如果数据量很大的话,全量同步需要大量的内存,如果内存不足的话则可能会导致内存溢出。

通常的会采用分页的方式,一批一批的同步,大体的实现方式如下:

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文件:

<select id="selectUsers" resultType="User" fetchSize="1000">
   SELECT userId from t_user
 </select>

自定义一个ResultHandler:

User是自定义的同步对象的实体对象,需要自己定义

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;
    }
}

使用代码示例:

SyncDataHandler syncDataHandler = new SyncDataHandler();
userMapper.getUserList("selectUsers", syncDataHandler);
syncDataHandler.end();

结言

流式查询可以避免 OOM,,数据量大可以考虑此方案,其占用内存大小取决于批处理大小BATCH_SIZE的设置。所以BATCH_SIZE应该根据业务情况设置合适的大小。但是这这种方式会占用数据库连接,使用中不会释放,所以线上针对大数据量业务用到流式操作,一定要进行并发控制。

到此这篇关于详解MyBatis如何在大数据量下使用流式查询进行数据同步的文章就介绍到这了,更多相关MyBatis流式查询内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • springcloud本地调试feign调用出现的诡异404问题及解决

    springcloud本地调试feign调用出现的诡异404问题及解决

    这篇文章主要介绍了springcloud本地调试feign调用出现的诡异404问题及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • Javaweb会话跟踪技术Cookie和Session的具体使用

    Javaweb会话跟踪技术Cookie和Session的具体使用

    本文主要介绍了Javaweb会话跟踪技术Cookie&Session的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • Java源码重读之ConcurrentHashMap详解

    Java源码重读之ConcurrentHashMap详解

    ConcurrentHashMap(CHM)是日常开发中使用频率非常高的一种数据结构。本文将从源码角度带大家深入了解一下ConcurrentHashMap的使用,需要的可以收藏一下
    2023-05-05
  • Spring bean 加载执行顺序实例解析

    Spring bean 加载执行顺序实例解析

    这篇文章主要介绍了Spring bean 加载执行顺序实例解析,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
    2018-02-02
  • Java如何基于反射获取对象属性信息

    Java如何基于反射获取对象属性信息

    这篇文章主要介绍了Java如何基于反射获取对象属性信息,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • 基于springboot的RestTemplate、okhttp和HttpClient对比分析

    基于springboot的RestTemplate、okhttp和HttpClient对比分析

    这篇文章主要介绍了基于springboot的RestTemplate、okhttp和HttpClient对比分析,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • SpringBoot异常错误页面实现方法介绍

    SpringBoot异常错误页面实现方法介绍

    在项目访问的时候我们经常会发生错误或者页面找不到,比如:资源找不到404,服务器500错误,默认情况下springboot的处理机制都是去跳转内部的错误地址:/error 和与之对应的一个错误页面
    2022-09-09
  • java抓取鼠标事件和鼠标滚轮事件示例

    java抓取鼠标事件和鼠标滚轮事件示例

    这篇文章主要介绍了java抓取鼠标事件和鼠标滚轮事件示例,需要的朋友可以参考下
    2014-05-05
  • SpringMVC实现文件上传和下载功能

    SpringMVC实现文件上传和下载功能

    这篇文章主要为大家详细介绍了SpringMVC实现文件上传和下载功能 ,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • Java 在volatile内部调用接口的方法

    Java 在volatile内部调用接口的方法

    在Java中,volatile 关键字通常用于确保变量的可见性和有序性,而不是用来修饰接口或方法调用的,这篇文章主要介绍了Java 在volatile内部调用接口的方法,需要的朋友可以参考下
    2024-07-07

最新评论