当前位置: 首页>美食达人 >

环球微速讯:MyBatis 在大数据量下使用流式查询进行数据同步

2023-05-20 04:45:41 来源: 博客园

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

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


(资料图)

``

```javaint page = 1;int pageNum = 1000;while (true){ UserQueryRequest request = new UserQueryRequest(); request.setPage(page); request.setPageSize(pageNum); PageInfo pageInfo = userMapper.getUserPage(request); if (CollectionUtils.isEmpty(pageInfo.getList()) ){ break; } List userList = pageInfo.getList(); // 具体的处理逻辑 省略 page ++;}```

这种实现方式虽然可以实现分批同步,但是同步的数据必须先提供实现分页的查询方式,如果数据源是通过复杂的连表查询来的,先实现一个分页查询更是会增加实现的复杂度。解决这个问题可以使用一种更为优雅的解决方式,即使用流失查询。

​ 流式查询,会建立长连接,利用服务端游标,每次读取一条加载到 JVM 内存,因此不会导致内存溢出。

## MyBatis 如何使用流式查询:

### 配置mapper.xml文件:

```xml```

### 自定义一个ResultHandler:

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

```javaimport 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: */@Slf4jpublic class SyncDataHandler implements ResultHandler {

/** * 每批处理数量 */ private final static int BATCH_SIZE = 1000;

/** * 缓存数据 */ private List cacheList = new ArrayList<>();

/** * 同步熟虑 */ private int total = 0;

@Override public void handleResult(ResultContext 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; }}```

### 使用代码示例:

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

## **结言**

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

标签: