一舷夺、前言
MySQL 是目前使用比較廣泛的關(guān)系型數(shù)據(jù)庫(kù),而從數(shù)據(jù)庫(kù)里面根據(jù)條件查詢數(shù)據(jù)到內(nèi)存的情況想必大家在日常項(xiàng)目實(shí)踐中都有使用箱熬。
當(dāng)指定條件的數(shù)據(jù)量特別大時(shí)候一般是通過(guò)分頁(yè)的方式在前端頁(yè)面通過(guò) Tag 標(biāo)簽一頁(yè)頁(yè)的加載數(shù)據(jù)到內(nèi)存吭狡;但是有些情況下卻不需要用戶切換 Tag 標(biāo)簽的方式一頁(yè)頁(yè)的加載數(shù)據(jù),這時(shí)候如果一下子全部把數(shù)據(jù)加載內(nèi)存攘宙,就有可能會(huì)導(dǎo)致 OOM屯耸,雖然這時(shí)候可以通過(guò)程序控制分頁(yè)查詢,但是每次查詢時(shí)候數(shù)據(jù)庫(kù)都需要把所有符合條件的數(shù)據(jù)查詢出來(lái)然后根據(jù)當(dāng)前頁(yè)的返回來(lái)返回指定的頁(yè)蹭劈,這無(wú)疑加重了 MySQL 服務(wù)器不必要的開(kāi)銷疗绣。
其實(shí)在 MySQL 中提供了流式查詢,這允許把符合條件的數(shù)據(jù)一部分一部分的加載到內(nèi)存铺韧,本 Chat 就來(lái)具體講解如何在 MySQL中使用流式查詢:
- 使用流式查詢前多矮,我們是如何在 MySQL 中進(jìn)行查詢數(shù)據(jù)的,整個(gè)過(guò)程發(fā)生了什么?
- 如何使用 JDBC 編程方式在 MySQL 中使用流式查詢塔逃?
二讯壶、普通查詢
- 當(dāng)我們?cè)贘VM進(jìn)程里面的某一個(gè)線程里面執(zhí)行數(shù)據(jù)庫(kù)查詢時(shí)候,其實(shí)這個(gè)請(qǐng)求首先會(huì)調(diào)用mysql驅(qū)動(dòng)程序湾盗。
- mysql驅(qū)動(dòng)接受到請(qǐng)求后會(huì)向MySQL服務(wù)器發(fā)起TCP請(qǐng)求伏蚊,服務(wù)器端根據(jù)條件查詢出匹配的數(shù)據(jù),然后通過(guò)TCP鏈接發(fā)送到MySQL驅(qū)動(dòng)
- MySQL驅(qū)動(dòng)內(nèi)則會(huì)把符合條件的數(shù)據(jù)緩存到驅(qū)動(dòng)內(nèi)格粪,等服務(wù)器返回了所有符合條件的數(shù)據(jù)后躏吊,在一下子把緩存里面的數(shù)據(jù)返回給調(diào)用sql的應(yīng)用程序。
所以如果查詢的數(shù)據(jù)量特別大帐萎,那么mysql驅(qū)動(dòng)內(nèi)緩存就可能把內(nèi)存撐爆造成OOM比伏。
三、JDBC編程中MySQL流式查詢
mysql客戶端流式查詢不會(huì)一下子把服務(wù)器端所有數(shù)據(jù)緩存起來(lái)疆导,而是一部分一部分的把服務(wù)器端返回的數(shù)據(jù)返回給應(yīng)用程序?qū)恿尴睿钥梢杂行П苊釵OM。
JDBC編程中MYSQL流式查詢例子:
public void selectData(String sqlCmd,) throws SQLException {
validate(sqlCmd);
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = petadataSource.getConnection();
stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);
rs = stmt.executeQuery();
try {
while(rs.next()){
try {
System.out.println("one:" + rs.getString(1) + "two:" + rs.getString(2) + "thrid:" + rs.getString(3));
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} finally {
close(stmt, rs, conn);
}
}
可知只是prepareStatement時(shí)候改變了參數(shù)為ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY澈段,并且設(shè)置了PreparedStatement的fetchsize為Integer.MIN_VALUE悠菜。
四、最后
上面我們講解了JDBC中流式查詢使用均蜜,那么如下在Mybatis中使用那李剖?
- 如何在 Mybatis 中使用 MyBatisCursorItemReader 進(jìn)行流式查詢?
- 如何在 Mybatis 中使用 ResultHandler 進(jìn)行流式查詢囤耳?
- 什么是客戶端流式查詢和服務(wù)器端流式查詢篙顺?
更多流式查詢請(qǐng)單擊 單擊我
我的博客即將搬運(yùn)同步至騰訊云+社區(qū),邀請(qǐng)大家一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=25hh8jpv4h34s