JDBC中Fetchsize的實現(xiàn)
1. 什么是fetchsize?
1.1 Oracle中的fetchsize
當我們執(zhí)行一個SQL查詢語句的時候,需要在客戶端和服務器端都打開一個游標,并且分別申請一塊內存空間,作為存放查詢的數(shù)據(jù)的一個緩沖區(qū)。這塊內存區(qū),存放多少條數(shù)據(jù)就由fetchsize來決定,同時每次網(wǎng)絡包會傳送fetchsize條記錄到客戶端。應該很容易理解,如果fetchsize設置為20,當我們從服務器端查詢數(shù)據(jù)往客戶端傳送時,每次可以傳送20條數(shù)據(jù),但是兩端分別需要20條數(shù)據(jù)的內存空閑來保存這些數(shù)據(jù)。fetchsize決定了每批次可以傳輸?shù)挠涗洍l數(shù),但同時,也決定了內存的大小。這塊內存,在oracle服務器端是動態(tài)分配的(大家可以想想為什么)。而在客戶端(JBOSS),PS對象會存在一個緩沖中(LRU鏈表),也就是說,這塊內存是事先配好的,應用端內存的分配在conn.prepareStatement(sql)或conn.CreateStatement(sql)的時候完成。
例如:
//打開游標,執(zhí)行查詢,但是并不獲取任何的數(shù)據(jù),網(wǎng)絡上沒有數(shù)據(jù)的傳輸。
rs = stmt.executeQuery();
//獲取具體的數(shù)據(jù),網(wǎng)絡一般每次傳輸fetchsize條數(shù)據(jù)。
while (rs.next()){
}1.2 Mysql中的fetchsize
Mysql的preparestament基本上不占用內存,為什么呢?因為Mysql并不需要象Oracle那樣的一塊內存來保存結果集緩沖區(qū),為什么不需要緩沖區(qū),其中根本的原因是由Mysql的通訊方式?jīng)Q定的。Mysql客戶端/服務器協(xié)議是半雙工的,即Mysql只能在給定的時間,發(fā)送或接受數(shù)據(jù),但不能同時發(fā)送和接收。所以,Mysql在數(shù)據(jù)查詢結果集傳送的時候,需要一次性將數(shù)據(jù)全部傳送到客戶端,在客戶數(shù)據(jù)接收完之后,釋放相關的鎖等資源。因為這種半雙工的通訊方式,所以Mysql不需要客戶端的游標,但是客戶端API通過把結果取到內存中,可以模擬游標的操作。所以,我們可以在JAVA程序中,可以象Oracle那樣來實現(xiàn)Mysql的訪問。
注意:
useCursorFetch=true 是針對 MySQL 數(shù)據(jù)庫的 JDBC 連接參數(shù),用于啟用服務器端游標獲取數(shù)據(jù)。在 MyBatis 中,當使用流式查詢(例如:分頁查詢、結果集處理和使用游標等)時,這個配置可以幫助逐行從服務器檢索數(shù)據(jù),而不是一次性將所有數(shù)據(jù)加載到內存中,從而降低內存占用。
當使用 MySQL 數(shù)據(jù)庫時,在 JDBC 連接字符串中加入 useCursorFetch=true,并結合設置合適的 fetchSize,可以避免因一次性加載過多數(shù)據(jù)導致的內存溢出問題。注意,此配置僅對 MySQL 數(shù)據(jù)庫有效。 如果不設置 useCursorFetch=true 這個配置,僅使用之前提到的那些配置(如設置 defaultFetchSize、分頁查詢、結果集處理和使用游標等),在大多數(shù)情況下,這些配置仍然可以有效地避免查詢導致的內存溢出。
但需要注意的是,對于 MySQL 數(shù)據(jù)庫,如果不啟用服務器端游標獲取數(shù)據(jù),這可能會影響到流式查詢的效果。因為在默認情況下,MySQL JDBC 驅動會一次性將所有數(shù)據(jù)加載到內存中。此時,即使使用了其他配置,也可能無法達到預期的內存優(yōu)化效果。
總的來說,在使用 MySQL 數(shù)據(jù)庫時,推薦在 JDBC 連接字符串中加入 useCursorFetch=true 配置,以更好地支持流式查詢和降低內存占用。在其他數(shù)據(jù)庫中,可以根據(jù)實際需求和場景選擇合適的配置和策略來避免查詢導致的內存溢出。
2. 使用fetchsize
2.1 fetchsize的作用
Java doc
Gives the JDBC driver a hint as to the number of rows that should be fetched from the database when more rows are needed for this ResultSet object. If the fetch size specified is zero, the JDBC driver ignores the value and is free to make its own best guess as to what the fetch size should be. The default value is set by the Statement object that created the result set. The fetch size may be changed at any time.
2.2 fetchsize的默認值
在ojdbc8的源碼中oracle的驅動的fetchsize參數(shù)的默認值是10


2.3 fetchsize的設置
2.3.1 Mybatis全局設置
通過設置 MyBatis 配置文件中的 defaultFetchSize 值:
<settings>
<setting name="defaultFetchSize" value="合適的值" />
</settings>2.3.2 語句級別的設置
可以在jdbc中調用Preparedstatement .setFetchSize()的進行設置:
stmt = conn.prepareStatement(sql); stmt.setFetchSize(50);
2.3.3 框架上直接針對某個語句進行設置
可以在Mybatis的查詢語句上進行設置:
<select id="selectFetchSize" fetchSize="100" resultSetType="FORWARD_ONLY" resultType="com.example.poi.entity.EntityDemo">
select * from entity_demo
</select>
Mybatis中的定義:
fetchSize:fetchSize屬性用于指定每次從數(shù)據(jù)庫獲取的記錄數(shù)。這個屬性可以用于控制查詢操作的內存使用和性能。
當設置fetchSize時,MyBatis會根據(jù)這個值來調整JDBC的Statement對象的fetchSize屬性。如果數(shù)據(jù)庫和JDBC驅動支持,這可以減少網(wǎng)絡往返次數(shù),提高性能。
在分頁查詢或處理大量數(shù)據(jù)時,合理設置fetchSize可以有效地控制每次從數(shù)據(jù)庫拉取的數(shù)據(jù)量,防止內存溢出。
在您的例子中,fetchSize="100"意味著每次從數(shù)據(jù)庫獲取100條記錄。
resultSetType:
resultSetType屬性用于定義結果集的滾動方向。MyBatis支持以下幾種類型:
FORWARD_ONLY:結果集只能向前滾動,這是默認值,適用于大多數(shù)情況。
SCROLL_SENSITIVE:結果集可以向前或向后滾動,并且可以檢測到數(shù)據(jù)庫中的數(shù)據(jù)變化。
SCROLL_INSENSITIVE:結果集可以向前或向后滾動,但不會檢測到數(shù)據(jù)庫中的數(shù)據(jù)變化。
這個屬性影響JDBC的Statement對象的resultSetType,它決定了結果集的可滾動性和可更新性。
在您的例子中,resultSetType="FORWARD_ONLY"意味著結果集只能向前滾動,這是最常用的類型,因為它通常提供更好的性能。
使用fetchSize和resultSetType可以幫助優(yōu)化查詢性能和資源使用。在處理大量數(shù)據(jù)或需要特定結果集行為時,這些屬性尤其有用。然而,它們的實際效果還取決于數(shù)據(jù)庫驅動程序和數(shù)據(jù)庫服務器的性能特性。
2.3.4 使用注解
在Mybatis3.2中可以使用注解:
@Select("select * from entity_demo t ${ew.customSqlSegment}")
@Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = 100)
@ResultType(Entity_demo.class)
void selectFetchSize(@Param(Constants.WRAPPER) QueryWrapper<Entity_demo> wrapper,ResultHandler<entity_demo> handler);到此這篇關于JDBC中Fetchsize的實現(xiàn)的文章就介紹到這了,更多相關JDBC Fetchsize內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- SpringBoot+MybatisPlus實現(xiàn)sharding-jdbc分庫分表的示例代碼
- JDBC如何連接mysql
- sharding-jdbc實現(xiàn)分頁查詢的示例代碼
- 解決mybatis plus報錯com.microsoft.sqlserver.jdbc.SQLServerException:必須執(zhí)行該語句才能獲得結果
- ShardingSphere JDBC強制路由使用的項目實踐
- springboot jdbctemplate如何實現(xiàn)多數(shù)據(jù)源
- sharding-jdbc 兼容 MybatisPlus動態(tài)數(shù)據(jù)源的配置方法
相關文章
springboot3.x版本集成log4j遇到Logging?system?failed?to?initial
使用Springboot?3.x集成Log4j時可能會遇到版本沖突的問題,這通??梢酝ㄟ^檢查Maven依賴樹來識別,一旦發(fā)現(xiàn)沖突,將Log4j的版本統(tǒng)一更新到最新的兼容版本,例如2.21.1,即可解決問題,此方法有效解決了日志打印錯誤,是處理類似問題的一個實用參考2024-09-09
Java中的FilterOutputStream 簡介_動力節(jié)點Java學院整理
FilterOutputStream 的作用是用來“封裝其它的輸出流,并為它們提供額外的功能”。它主要包括BufferedOutputStream, DataOutputStream和PrintStream。接下來通過本文給大家簡單介紹下FilterOutputStream知識,需要的朋友參考下吧2017-05-05
SpringMVC實現(xiàn)前端后臺交互傳遞數(shù)據(jù)
本篇文章主要介紹了SpringMVC實現(xiàn)前端后臺傳遞數(shù)據(jù)的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-03-03

