詳解MyBatis如何在大數(shù)據(jù)量下使用流式查詢進(jìn)行數(shù)據(jù)同步
通常的數(shù)據(jù)同步中,如果數(shù)據(jù)量比較少的話可以直接全量同步,默認(rèn)情況下,完整的檢索結(jié)果集會(huì)將其存儲(chǔ)在內(nèi)存中。在大多數(shù)情況下,這是最有效的操作方式,并且由于 MySQL 網(wǎng)絡(luò)協(xié)議的設(shè)計(jì),因此更易于實(shí)現(xiàn)。但是如果數(shù)據(jù)量很大的話,全量同步需要大量的內(nèi)存,如果內(nèi)存不足的話則可能會(huì)導(dǎo)致內(nèi)存溢出。
通常的會(huì)采用分頁(yè)的方式,一批一批的同步,大體的實(shí)現(xiàn)方式如下:
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 ++; }
這種實(shí)現(xiàn)方式雖然可以實(shí)現(xiàn)分批同步,但是同步的數(shù)據(jù)必須先提供實(shí)現(xiàn)分頁(yè)的查詢方式,如果數(shù)據(jù)源是通過復(fù)雜的連表查詢來(lái)的,先實(shí)現(xiàn)一個(gè)分頁(yè)查詢更是會(huì)增加實(shí)現(xiàn)的復(fù)雜度。解決這個(gè)問題可以使用一種更為優(yōu)雅的解決方式,即使用流失查詢。
流式查詢,會(huì)建立長(zhǎng)連接,利用服務(wù)端游標(biāo),每次讀取一條加載到 JVM 內(nèi)存,因此不會(huì)導(dǎo)致內(nèi)存溢出。
MyBatis 如何使用流式查詢:
配置mapper.xml文件:
<select id="selectUsers" resultType="User" fetchSize="1000"> SELECT userId from t_user </select>
自定義一個(gè)ResultHandler:
User是自定義的同步對(duì)象的實(shí)體對(duì)象,需要自己定義
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> { /** * 每批處理數(shù)量 */ private final static int BATCH_SIZE = 1000; /** * 緩存數(shù)據(jù) */ 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); //每到達(dá)BATCH_SIZE 條數(shù)據(jù)處理一次 if (this.cacheList.size() >= BATCH_SIZE) { this.handle(); } total++; } /** * 處理緩存數(shù)據(jù) */ private void handle() { try { // 具體的處理邏輯 省略 } finally { // 清除處理過的緩存數(shù)據(jù) this.cacheList.clear(); } } /** * 處理最后一批沒有進(jìn)行處理的數(shù)據(jù) */ public int end() { this.end(); return total; } }
使用代碼示例:
SyncDataHandler syncDataHandler = new SyncDataHandler(); userMapper.getUserList("selectUsers", syncDataHandler); syncDataHandler.end();
結(jié)言
流式查詢可以避免 OOM,,數(shù)據(jù)量大可以考慮此方案,其占用內(nèi)存大小取決于批處理大小BATCH_SIZE的設(shè)置。所以BATCH_SIZE應(yīng)該根據(jù)業(yè)務(wù)情況設(shè)置合適的大小。但是這這種方式會(huì)占用數(shù)據(jù)庫(kù)連接,使用中不會(huì)釋放,所以線上針對(duì)大數(shù)據(jù)量業(yè)務(wù)用到流式操作,一定要進(jìn)行并發(fā)控制。
到此這篇關(guān)于詳解MyBatis如何在大數(shù)據(jù)量下使用流式查詢進(jìn)行數(shù)據(jù)同步的文章就介紹到這了,更多相關(guān)MyBatis流式查詢內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springcloud本地調(diào)試feign調(diào)用出現(xiàn)的詭異404問題及解決
這篇文章主要介紹了springcloud本地調(diào)試feign調(diào)用出現(xiàn)的詭異404問題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03Javaweb會(huì)話跟蹤技術(shù)Cookie和Session的具體使用
本文主要介紹了Javaweb會(huì)話跟蹤技術(shù)Cookie&Session的具體使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07

基于springboot的RestTemplate、okhttp和HttpClient對(duì)比分析

SpringBoot異常錯(cuò)誤頁(yè)面實(shí)現(xiàn)方法介紹

java抓取鼠標(biāo)事件和鼠標(biāo)滾輪事件示例

SpringMVC實(shí)現(xiàn)文件上傳和下載功能

Java 在volatile內(nèi)部調(diào)用接口的方法