最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Mybatis集成MySQL使用游標(biāo)查詢處理大批量數(shù)據(jù)方式

 更新時(shí)間:2024年01月27日 09:50:12   作者:WannaRunning  
這篇文章主要介紹了Mybatis集成MySQL使用游標(biāo)查詢處理大批量數(shù)據(jù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

背景

基于數(shù)據(jù)的時(shí)間范圍查詢,給符合條件的用戶推送積分即將到期的提醒。

初期用戶量小使用最普通簡(jiǎn)單的分頁查詢掃描數(shù)據(jù)處理數(shù)據(jù)沒問題。隨著用戶量的上升表數(shù)據(jù)已經(jīng)上千萬,每天掃描處理的數(shù)量也超百萬,limit分頁出現(xiàn)了慢sql,任務(wù)執(zhí)行時(shí)間也達(dá)不到預(yù)期了。

上述方案出現(xiàn)瓶頸后考慮放棄limit方案,使用游標(biāo)的方式進(jìn)行全量數(shù)據(jù)的獲取,這樣一來SQL執(zhí)行快任務(wù)執(zhí)行也快。

MySQL游標(biāo)查詢

useCursorFetch

使用游標(biāo)查詢時(shí),必須在jdbc url上設(shè)置連接屬性參數(shù)useCursorFetch=true

FetchSize

在設(shè)置了useCursorFetch=true后,需要在SQL中指定fetchSize,即一次獲取的數(shù)據(jù)量。

如果不設(shè)置fetchSize參數(shù),則執(zhí)行時(shí)仍然是全量返回,可能會(huì)出現(xiàn)OOM。

Mybatis集成Cursor查詢

mapper接口方法返回值聲明為Cursor類型,下面是SQL和Mapper的示例。

Cursor<Long> selectExpireCouponMember(@Param("endTime") String endTime);
 
 
<select id="selectExpireCouponMember" resultType="java.lang.Long" fetchSize="5000">
	select
		distinct member_id
	from t_dj_coupon
	where
	   end_time > end_time < #{endStartTime} and end_time < #{endTime}
</select>

下面是基于上面的SQL做大量數(shù)據(jù)查詢后寫入文件的代碼示例。

String fileName = DateFormatUtils.format(System.currentTimeMillis(), DateUtils.PATTERN_YYYY_MM_DD) + "_status_push_member.txt";
File file = new File(fileName);
file.createNewFile();
 
fileWriter = new FileWriter(file);
bufferedWriter = new BufferedWriter(fileWriter);
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
	DjCouponMapper mapper = sqlSession.getMapper(DjCouponMapper.class);
	try (Cursor<Long> cursor = mapper.selectStartCouponMember(startDate, startDateEnd, BrandContextHolder.getBrandMdCode())) {
		Iterator<Long> iterator = cursor.iterator();
		Set<Long> couponMemberSet = new HashSet<>(pageSize.intValue());
		while (iterator.hasNext()) {
			couponMemberSet.add(iterator.next());
			writeNum++;
			if (couponMemberSet.size() >= pageSize) {
				bufferedWriter.write(couponMemberSet.toString());
				bufferedWriter.newLine();
				bufferedWriter.flush();
				writeLine++;
				couponMemberSet.clear();
			}
		
		}
		if (CollectionUtils.isNotEmpty(couponMemberSet)) {
			bufferedWriter.write(couponMemberSet.toString());
			bufferedWriter.newLine();
			bufferedWriter.flush();
			writeLine++;
		}
	}
}

Mybatis是如何實(shí)現(xiàn)基于Cursor查詢的

com.mysql.cj.jdbc.result.ResultSetImpl實(shí)現(xiàn)類

ResultSetImpl 是mybatis中實(shí)現(xiàn)游標(biāo)查詢結(jié)果解析的類。

這個(gè)實(shí)現(xiàn)類的next方法中調(diào)用了ResultsetRows接口的next方法。

ResultsetRows接口

ResultsetRows接口有ResultsetRowsCursor,ResultsetRowsStatic,ResultsetRowsStreaming三個(gè)實(shí)現(xiàn)類。

本文寫的游標(biāo)查詢的場(chǎng)景,使用的是ResultsetRowsCursor這個(gè)實(shí)現(xiàn)類。

詳細(xì)看下ResultsetRowsCursor這個(gè)實(shí)現(xiàn)類,主要是實(shí)現(xiàn)了Iterator的hasNext和next方法,這也是使用Cursor獲取數(shù)據(jù)需要的兩個(gè)方法。

下面是hasnext方法的邏輯,根據(jù)下次要獲取的游標(biāo)索引和當(dāng)前本地?cái)?shù)據(jù)集計(jì)算返回是否還有后續(xù)數(shù)據(jù)可以獲取。

下面是next方法的邏輯,先執(zhí)行一下hasnext的邏輯判斷,再取值

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論

维西| 濮阳县| 灵寿县| 望城县| 冕宁县| 巫山县| 博兴县| 昭觉县| 贺兰县| 苗栗县| 双鸭山市| 长顺县| 吉林省| 乌恰县| 翁源县| 武穴市| 宜良县| 乐都县| 小金县| 蛟河市| 赞皇县| 弥渡县| 台湾省| 黑山县| 邹平县| 沛县| 通辽市| 中超| 台州市| 蓬安县| 瑞丽市| 太原市| 乌恰县| 西峡县| 榆树市| 宜昌市| 辉县市| 沁源县| 曲松县| 邯郸县| 象州县|