java操作mysql遇到大量數(shù)據(jù)會(huì)存在內(nèi)存溢出的危險(xiǎn)
分為兩部分一個(gè)是java層方面,還有一個(gè)是mysql層
java
普通的方式
- 1.java發(fā)出請(qǐng)求蛉加,mysql響應(yīng)
- 2.java獲取數(shù)據(jù)的時(shí)候是不停地把緩沖區(qū)數(shù)據(jù)撈到內(nèi)存中蚜枢,一直到數(shù)據(jù)發(fā)送結(jié)束,等到所有數(shù)據(jù)獲取完畢针饥。我們客戶(hù)端才能進(jìn)一步操作厂抽,這就導(dǎo)致OOM
- 3.客戶(hù)端只需要主動(dòng)通信一次,剩余的都是服務(wù)器端主動(dòng)推送數(shù)據(jù)
useCursorFetch
- 1.每次都要主動(dòng)去請(qǐng)求指定大小的數(shù)據(jù)丁眼,這回導(dǎo)致通信頻繁
- 2.當(dāng)數(shù)據(jù)量很大的時(shí)候筷凤,為了避免長(zhǎng)期占用索引數(shù)據(jù),會(huì)把查詢(xún)到的所有數(shù)據(jù)建立臨時(shí)表
采用statement.setFetchSize(Integer.MIN_VALUE)并確保游標(biāo)是只讀向前滾動(dòng)的即可(為游標(biāo)的默認(rèn)值)苞七,也可以強(qiáng)制類(lèi)型轉(zhuǎn)換為com.mysql.jdbc.StatementImpl藐守,然后調(diào)用其內(nèi)部方法:enableStreamingResults()這樣讀取數(shù)據(jù)內(nèi)存就不會(huì)掛掉了
- 1.客戶(hù)端只需要主動(dòng)通信一次,剩余的都是服務(wù)器端主動(dòng)推送數(shù)據(jù)
- 2.客戶(hù)端每次只從buffer里面獲取一部分?jǐn)?shù)據(jù)即響應(yīng)給業(yè)務(wù)蹂风,業(yè)務(wù)處理完成之后繼續(xù)從buffer獲取卢厂,服務(wù)端感受到客戶(hù)端的buffer不滿(mǎn)的時(shí)候會(huì)自動(dòng)發(fā)送
Mysql層
單表查詢(xún)mysql如何返回
- 1.客戶(hù)端請(qǐng)求到了之后,server層讓引擎層去執(zhí)行惠啄,引擎層獲取到一個(gè)記錄后就立即發(fā)送給客戶(hù)端
多表查詢(xún)mysql如何返回
- 1.驅(qū)動(dòng)表執(zhí)行完畢一次之后會(huì)形成一個(gè)結(jié)果集慎恒,然后被驅(qū)動(dòng)表會(huì)多次執(zhí)行(執(zhí)行次數(shù)就是驅(qū)動(dòng)表的大腥文凇)每次取得一個(gè)完整記錄也是立馬發(fā)送
- 2.如果驅(qū)動(dòng)表的結(jié)果集太大則會(huì)形成物化表(臨時(shí)表,有基于內(nèi)存的 如果再大則會(huì)變成B+樹(shù)存儲(chǔ)到磁盤(pán))
總結(jié)
- 1.客戶(hù)端采用stream方式最好融柬,服務(wù)端則不用關(guān)心內(nèi)存的問(wèn)題