哈哈哈哈哈操欧洲电影,久草网在线,亚洲久久熟女熟妇视频,麻豆精品色,久久福利在线视频,日韩中文字幕的,淫乱毛视频一区,亚洲成人一二三,中文人妻日韩精品电影

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何從MySQL數(shù)據(jù)庫(kù)里讀取100w數(shù)據(jù)行進(jìn)行處理呢?

數(shù)據(jù)分析與開(kāi)發(fā) ? 來(lái)源:CSDN ? 2023-03-17 17:13 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

背景

大數(shù)據(jù)量操作的場(chǎng)景大致如下:

數(shù)據(jù)遷移

數(shù)據(jù)導(dǎo)出

批量處理數(shù)據(jù)

在實(shí)際工作中當(dāng)指定查詢(xún)數(shù)據(jù)過(guò)大時(shí),我們一般使用分頁(yè)查詢(xún)的方式一頁(yè)一頁(yè)的將數(shù)據(jù)放到內(nèi)存處理。但有些情況不需要分頁(yè)的方式查詢(xún)數(shù)據(jù)或分很大一頁(yè)查詢(xún)數(shù)據(jù)時(shí),如果一下子將數(shù)據(jù)全部加載出來(lái)到內(nèi)存中,很可能會(huì)發(fā)生OOM(內(nèi)存溢出);而且查詢(xún)會(huì)很慢,因?yàn)榭蚣芎馁M(fèi)大量的時(shí)間和內(nèi)存去把數(shù)據(jù)庫(kù)查詢(xún)的結(jié)果封裝成我們想要的對(duì)象(實(shí)體類(lèi))。

舉例:在業(yè)務(wù)系統(tǒng)需要從 MySQL 數(shù)據(jù)庫(kù)里讀取 100w 數(shù)據(jù)行進(jìn)行處理,應(yīng)該怎么做?

做法通常如下:

常規(guī)查詢(xún): 一次性讀取 100w 數(shù)據(jù)到 JVM 內(nèi)存中,或者分頁(yè)讀取

流式查詢(xún): 建立長(zhǎng)連接,利用服務(wù)端游標(biāo),每次讀取一條加載到 JVM 內(nèi)存(多次獲取,一次一行)

游標(biāo)查詢(xún): 和流式一樣,通過(guò) fetchSize 參數(shù),控制一次讀取多少條數(shù)據(jù)(多次獲取,一次多行)

常規(guī)查詢(xún)

默認(rèn)情況下,完整的檢索結(jié)果集會(huì)將其存儲(chǔ)在內(nèi)存中。在大多數(shù)情況下,這是最有效的操作方式,并且由于 MySQL 網(wǎng)絡(luò)協(xié)議的設(shè)計(jì),因此更易于實(shí)現(xiàn)。

舉例:假設(shè)單表 100w 數(shù)據(jù)量,一般會(huì)采用分頁(yè)的方式查詢(xún):

@Mapper
publicinterfaceBigDataSearchMapperextendsBaseMapper{

@Select("SELECTbds.*FROMbig_data_searchbds${ew.customSqlSegment}")
PagepageList(@Param("page")Pagepage,@Param(Constants.WRAPPER)QueryWrapperqueryWrapper);

}

注:該示例使用的 MybatisPlus。

該方式比較簡(jiǎn)單,如果在不考慮 LIMIT 深分頁(yè)優(yōu)化情況下,估計(jì)你的數(shù)據(jù)庫(kù)服務(wù)器就噶皮了,或者你能等上幾十分鐘或幾小時(shí),甚至幾天時(shí)間檢索數(shù)據(jù)。

流式查詢(xún)

流式查詢(xún)指的是查詢(xún)成功后不是返回一個(gè)集合而是返回一個(gè)迭代器,應(yīng)用每次從迭代器取一條查詢(xún)結(jié)果。流式查詢(xún)的好處是能夠降低內(nèi)存使用。

如果沒(méi)有流式查詢(xún),我們想要從數(shù)據(jù)庫(kù)取 100w 條記錄而又沒(méi)有足夠的內(nèi)存時(shí),就不得不分頁(yè)查詢(xún),而分頁(yè)查詢(xún)效率取決于表設(shè)計(jì),如果設(shè)計(jì)的不好,就無(wú)法執(zhí)行高效的分頁(yè)查詢(xún)。因此流式查詢(xún)是一個(gè)數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)框架必須具備的功能。

MyBatis 中使用流式查詢(xún)避免數(shù)據(jù)量過(guò)大導(dǎo)致 OOM ,但在流式查詢(xún)的過(guò)程當(dāng)中,數(shù)據(jù)庫(kù)連接是保持打開(kāi)狀態(tài)的,因此要注意的是:

執(zhí)行一個(gè)流式查詢(xún)后,數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)框架就不負(fù)責(zé)關(guān)閉數(shù)據(jù)庫(kù)連接了,需要應(yīng)用在取完數(shù)據(jù)后自己關(guān)閉。

必須先讀?。ɑ蜿P(guān)閉)結(jié)果集中的所有行,然后才能對(duì)連接發(fā)出任何其他查詢(xún),否則將引發(fā)異常。

MyBatis 流式查詢(xún)接口

MyBatis 提供了一個(gè)叫 org.apache.ibatis.cursor.Cursor 的接口類(lèi)用于流式查詢(xún),這個(gè)接口繼承了 java.io.Closeable 和 java.lang.Iterable 接口,由此可知:

Cursor 是可關(guān)閉的;

Cursor 是可遍歷的。

除此之外,Cursor 還提供了三個(gè)方法:

isOpen(): 用于在取數(shù)據(jù)之前判斷 Cursor 對(duì)象是否是打開(kāi)狀態(tài)。只有當(dāng)打開(kāi)時(shí) Cursor 才能取數(shù)據(jù);

isConsumed(): 用于判斷查詢(xún)結(jié)果是否全部取完。

getCurrentIndex(): 返回已經(jīng)獲取了多少條數(shù)據(jù)

使用流式查詢(xún),則要保持對(duì)產(chǎn)生結(jié)果集的語(yǔ)句所引用的表的并發(fā)訪(fǎng)問(wèn),因?yàn)槠洳樵?xún)會(huì)獨(dú)占連接,所以必須盡快處理。

為什么要用流式查詢(xún)?

如果有一個(gè)很大的查詢(xún)結(jié)果需要遍歷處理,又不想一次性將結(jié)果集裝入客戶(hù)端內(nèi)存,就可以考慮使用流式查詢(xún);

分庫(kù)分表場(chǎng)景下,單個(gè)表的查詢(xún)結(jié)果集雖然不大,但如果某個(gè)查詢(xún)跨了多個(gè)庫(kù)多個(gè)表,又要做結(jié)果集的合并、排序等動(dòng)作,依然有可能撐爆內(nèi)存;詳細(xì)研究了sharding-sphere的代碼不難發(fā)現(xiàn),除了group by與order by字段不一樣之外,其他的場(chǎng)景都非常適合使用流式查詢(xún),可以最大限度的降低對(duì)客戶(hù)端內(nèi)存的消耗。

游標(biāo)查詢(xún)

對(duì)大量數(shù)據(jù)進(jìn)行處理時(shí),為防止內(nèi)存泄漏情況發(fā)生,也可以采用游標(biāo)方式進(jìn)行數(shù)據(jù)查詢(xún)處理。這種處理方式比常規(guī)查詢(xún)要快很多。

當(dāng)查詢(xún)百萬(wàn)級(jí)的數(shù)據(jù)的時(shí)候,還可以使用游標(biāo)方式進(jìn)行數(shù)據(jù)查詢(xún)處理,不僅可以節(jié)省內(nèi)存的消耗,而且還不需要一次性取出所有數(shù)據(jù),可以進(jìn)行逐條處理或逐條取出部分批量處理。一次查詢(xún)指定 fetchSize 的數(shù)據(jù),直到把數(shù)據(jù)全部處理完。

Mybatis 的處理加了兩個(gè)注解:@Options 和 @ResultType

@Mapper
publicinterfaceBigDataSearchMapperextendsBaseMapper{

//方式一多次獲取,一次多行
@Select("SELECTbds.*FROMbig_data_searchbds${ew.customSqlSegment}")
@Options(resultSetType=ResultSetType.FORWARD_ONLY,fetchSize=1000000)
PagepageList(@Param("page")Pagepage,@Param(Constants.WRAPPER)QueryWrapperqueryWrapper);

//方式二一次獲取,一次一行
@Select("SELECTbds.*FROMbig_data_searchbds${ew.customSqlSegment}")
@Options(resultSetType=ResultSetType.FORWARD_ONLY,fetchSize=100000)
@ResultType(BigDataSearchEntity.class)
voidlistData(@Param(Constants.WRAPPER)QueryWrapperqueryWrapper,ResultHandlerhandler);

}

@Options

ResultSet.FORWORD_ONLY:結(jié)果集的游標(biāo)只能向下滾動(dòng)

ResultSet.SCROLL_INSENSITIVE:結(jié)果集的游標(biāo)可以上下移動(dòng),當(dāng)數(shù)據(jù)庫(kù)變化時(shí),當(dāng)前結(jié)果集不變

ResultSet.SCROLL_SENSITIVE:返回可滾動(dòng)的結(jié)果集,當(dāng)數(shù)據(jù)庫(kù)變化時(shí),當(dāng)前結(jié)果集同步改變

fetchSize:每次獲取量

@ResultType

@ResultType(BigDataSearchEntity.class):轉(zhuǎn)換成返回實(shí)體類(lèi)型

注意:返回類(lèi)型必須為 void ,因?yàn)椴樵?xún)的結(jié)果在 ResultHandler 里處理數(shù)據(jù),所以這個(gè) hander 也是必須的,可以使用 lambda 實(shí)現(xiàn)一個(gè)依次處理邏輯。

注意:

雖然上面的代碼中都有 @Options 但實(shí)際操作卻有不同:

方式一是多次查詢(xún),一次返回多條;

方式二是一次查詢(xún),一次返回一條;

原因:

Oracle 是從服務(wù)器一次取出 fetch size 條記錄放在客戶(hù)端,客戶(hù)端處理完成一個(gè)批次后再向服務(wù)器取下一個(gè)批次,直到所有數(shù)據(jù)處理完成。

MySQL 是在執(zhí)行 ResultSet.next() 方法時(shí),會(huì)通過(guò)數(shù)據(jù)庫(kù)連接一條一條的返回。flush buffer 的過(guò)程是阻塞式的,如果網(wǎng)絡(luò)中發(fā)生了擁塞,send buffer 被填滿(mǎn),會(huì)導(dǎo)致 buffer 一直 flush 不出去,那 MySQL 的處理線(xiàn)程會(huì)阻塞,從而避免數(shù)據(jù)把客戶(hù)端內(nèi)存撐爆。

非流式查詢(xún)和流式查詢(xún)區(qū)別:

非流式查詢(xún):內(nèi)存會(huì)隨著查詢(xún)記錄的增長(zhǎng)而近乎直線(xiàn)增長(zhǎng)。

流式查詢(xún):內(nèi)存會(huì)保持穩(wěn)定,不會(huì)隨著記錄的增長(zhǎng)而增長(zhǎng)。其內(nèi)存大小取決于批處理大小BATCH_SIZE的設(shè)置,該尺寸越大,內(nèi)存會(huì)越大。所以BATCH_SIZE應(yīng)該根據(jù)業(yè)務(wù)情況設(shè)置合適的大小。

另外要切記每次處理完一批結(jié)果要記得釋放存儲(chǔ)每批數(shù)據(jù)的臨時(shí)容器,即上文中的gxids.clear();





審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • JAVA
    +關(guān)注

    關(guān)注

    20

    文章

    3006

    瀏覽量

    116835
  • MySQL
    +關(guān)注

    關(guān)注

    1

    文章

    931

    瀏覽量

    29753
  • JVM
    JVM
    +關(guān)注

    關(guān)注

    0

    文章

    161

    瀏覽量

    13086
  • MYSQL數(shù)據(jù)庫(kù)

    關(guān)注

    0

    文章

    98

    瀏覽量

    10302

原文標(biāo)題:面試官:從 MySQL 讀取 100w 數(shù)據(jù)進(jìn)行處理,應(yīng)該怎么做?

文章出處:【微信號(hào):DBDevs,微信公眾號(hào):數(shù)據(jù)分析與開(kāi)發(fā)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    怎么簡(jiǎn)單實(shí)現(xiàn)由Labview讀取的串口數(shù)據(jù)自增寫(xiě)入mysql5.7數(shù)據(jù)庫(kù)中?

    怎么簡(jiǎn)單實(shí)現(xiàn)由Labview讀取的串口數(shù)據(jù)自增寫(xiě)入mysql5.7數(shù)據(jù)庫(kù)中? 已實(shí)現(xiàn):串口數(shù)據(jù)的接收
    發(fā)表于 01-11 22:05

    求大神現(xiàn)身,如何讀取數(shù)據(jù)庫(kù)里指定的文件?

    大神們,如何讀取數(shù)據(jù)庫(kù)里指定的文件?我的數(shù)據(jù)庫(kù)里記錄了特征值,是按日期存儲(chǔ)的,如何讀取某一段時(shí)間內(nèi)的特征值內(nèi)容?比如我要設(shè)置一個(gè)日期起始輸入框,就能
    發(fā)表于 03-22 11:54

    labview插入數(shù)據(jù)MySQL數(shù)據(jù)庫(kù)

    最近在用labview寫(xiě)入數(shù)據(jù)MySQL數(shù)據(jù)庫(kù),遇到一個(gè)問(wèn)題:(如圖片所示)利用insert指令插入數(shù)據(jù),為什么每次插入單個(gè)值都會(huì)新起一行,而不會(huì)自動(dòng)插入在連續(xù)的非空下一行
    發(fā)表于 12-26 16:52

    數(shù)據(jù)庫(kù)讀取數(shù)據(jù)問(wèn)題

    本帖最后由 控制發(fā)燒友 于 2020-7-9 08:48 編輯 如圖所示,我想讀取MySQL數(shù)據(jù)庫(kù)里數(shù)據(jù),當(dāng)我字段設(shè)置成字符串形式A B C時(shí)
    發(fā)表于 07-09 08:46

    MySQL數(shù)據(jù)庫(kù)Access存儲(chǔ)讀取SQL語(yǔ)句

    LabVIEW視頻教程MySQL數(shù)據(jù)庫(kù)Access存儲(chǔ)讀取SQL語(yǔ)句
    發(fā)表于 10-21 11:59

    MySQL端口可以MySQL數(shù)據(jù)庫(kù)中存儲(chǔ)和檢索數(shù)據(jù)

    MySQL端口可以MySQL數(shù)據(jù)庫(kù)中存儲(chǔ)和檢索數(shù)據(jù)。 概覽 建立連接后,端口讀取
    的頭像 發(fā)表于 02-15 14:07 ?2409次閱讀

    華為云數(shù)據(jù)庫(kù)-RDS for MySQL數(shù)據(jù)庫(kù)

    華為云數(shù)據(jù)庫(kù)-RDS for MySQL數(shù)據(jù)庫(kù) 華為云數(shù)據(jù)庫(kù)作為華為云的一款數(shù)據(jù)庫(kù)產(chǎn)品,它主要是以MyS
    的頭像 發(fā)表于 10-27 11:06 ?2476次閱讀

    有哪些不同的MySQL數(shù)據(jù)庫(kù)引擎?

    數(shù)據(jù)庫(kù)引擎是MySQL組件,可以處理SQL操作,例如從數(shù)據(jù)庫(kù)創(chuàng)建、讀取和更新數(shù)據(jù)。
    的頭像 發(fā)表于 04-03 16:38 ?2238次閱讀

    python讀取數(shù)據(jù)庫(kù)數(shù)據(jù) python查詢(xún)數(shù)據(jù)庫(kù) python數(shù)據(jù)庫(kù)連接

    python讀取數(shù)據(jù)庫(kù)數(shù)據(jù) python查詢(xún)數(shù)據(jù)庫(kù) python數(shù)據(jù)庫(kù)連接 Python是一門(mén)高級(jí)編程語(yǔ)言,廣泛應(yīng)用于各種領(lǐng)域。其中,Pyt
    的頭像 發(fā)表于 08-28 17:09 ?3257次閱讀

    MySQL數(shù)據(jù)庫(kù)管理與應(yīng)用

    討論MySQL數(shù)據(jù)庫(kù)的管理和應(yīng)用。 管理MySQL數(shù)據(jù)庫(kù) 在管理MySQL數(shù)據(jù)庫(kù)之前,我們需要了
    的頭像 發(fā)表于 08-28 17:15 ?1948次閱讀

    mysql數(shù)據(jù)庫(kù)基礎(chǔ)命令

    MySQL是一個(gè)流行的關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng),經(jīng)常用于存儲(chǔ)、管理和操作數(shù)據(jù)。在本文中,我們將詳細(xì)介紹MySQL的基礎(chǔ)命令,并提供與每個(gè)命令相關(guān)的詳細(xì)解釋。 登錄
    的頭像 發(fā)表于 12-06 10:56 ?1551次閱讀

    eclipse怎么連接數(shù)據(jù)庫(kù)mysql

    連接Eclipse和MySQL數(shù)據(jù)庫(kù)可以通過(guò)JDBC(Java Database Connectivity)來(lái)實(shí)現(xiàn)。以下是詳細(xì)步驟: 下載并安裝MySQL數(shù)據(jù)庫(kù):你首先需要下載并安裝
    的頭像 發(fā)表于 12-06 11:06 ?2212次閱讀

    數(shù)據(jù)庫(kù)數(shù)據(jù)恢復(fù)—未開(kāi)啟binlog的Mysql數(shù)據(jù)庫(kù)數(shù)據(jù)恢復(fù)案例

    。 mysql數(shù)據(jù)庫(kù)故障: 工作人員使用Delete命令刪除數(shù)據(jù)時(shí)未添加where子句進(jìn)行篩選,導(dǎo)致全表數(shù)據(jù)被刪除,刪除后未對(duì)該表
    的頭像 發(fā)表于 12-08 14:18 ?2192次閱讀
    <b class='flag-5'>數(shù)據(jù)庫(kù)</b><b class='flag-5'>數(shù)據(jù)</b>恢復(fù)—未開(kāi)啟binlog的<b class='flag-5'>Mysql</b><b class='flag-5'>數(shù)據(jù)庫(kù)</b><b class='flag-5'>數(shù)據(jù)</b>恢復(fù)案例

    MySQL數(shù)據(jù)庫(kù)的安裝

    MySQL數(shù)據(jù)庫(kù)的安裝 【一】各種數(shù)據(jù)庫(kù)的端口 MySQL :3306 Redis :6379 MongoDB :27017 Django :8000 flask :5000 【二】
    的頭像 發(fā)表于 01-14 11:25 ?1248次閱讀
    <b class='flag-5'>MySQL</b><b class='flag-5'>數(shù)據(jù)庫(kù)</b>的安裝

    MySQL數(shù)據(jù)庫(kù)是什么

    MySQL數(shù)據(jù)庫(kù)是一種 開(kāi)源的關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)(RDBMS) ,由瑞典MySQL AB公司開(kāi)發(fā),后被Oracle公司收購(gòu)。它通過(guò)結(jié)構(gòu)化查詢(xún)語(yǔ)言(SQL)
    的頭像 發(fā)表于 05-23 09:18 ?1450次閱讀
    信宜市| 霍州市| 苏州市| 高要市| 会东县| 万源市| 化州市| 浮梁县| 洪泽县| 涿鹿县| 贵阳市| 浏阳市| 肇源县| 天镇县| 海晏县| 三台县| 灌云县| 南木林县| 平昌县| 周口市| 孝义市| 红河县| 兴山县| 绥化市| 昌都县| 衢州市| 奇台县| 莲花县| 新竹县| 垦利县| 香格里拉县| 墨玉县| 周口市| 皮山县| 三明市| 德昌县| 乌拉特中旗| 什邡市| 香港 | 左云县| 五家渠市|