1. 程式人生 > >六、六、ibatis1.2.8查詢性能優化,實現百萬數據zip導出

六、六、ibatis1.2.8查詢性能優化,實現百萬數據zip導出

技術分享 復合索引 result 時間 .net 分享圖片 finish 行數 大量

經測試發現將查詢的結果100萬數據(池子中共有大概14億的數據)寫入Excle文件並進行壓縮導出zip文件最耗時的地方竟然在查詢,因此本篇文章主要是針對如何在spring+ibatis1.2.8中優化查詢
1)對查詢的SQL進行優化,表數據量特別大(上億、上十億)的時候可以按照查詢條件中的某個字段如:finish_time進行分區存儲或者建立復合索引或者分區復合索引
2)有博友說在ibatis映射器<select>元素中增加fetchSize屬性,可惜ibatis1.2.8不支持該屬性。其在2.0版本中才增加了該屬性(未確認是否屬實)。讓人豁然開朗的是
在Statement和ResultSet接口中都有提供有setFetchSize方法,因此優化的出發點就有了。使用spring的JdbcTemplate獲取數據源信息後再使原始的jdbc方法進行查詢優化
<select id="getPersonCount" resultClass="PoersonResult" parameterClass="PoersonBean" fetchSize="1000">

1、什麽是fetchSize


對Oracle中的fetchsize的理解,當我們執行一個SQL查詢語句的時候,需要在客戶端和服務器端都打開一個遊標,並且分別申請一塊內存空間,作為存放查詢的數據的一個緩沖區。這塊內存區,存放多少條數據就由fetchsize來決定,同時每次網絡包會傳送fetchsize條記錄到客戶端。應該很容易理解,如果fetchsize設置為20,當我們從服務器端查詢數據往客戶端傳送時,每次可以傳送20條數據,但是兩端分別需要20條數據的內存空閑來保存這些數據。fetchsize決定了每批次可以傳輸的記錄條數,但同時,也決定了內存的大小。這塊內存,在oracle服務器端是動態分配的(大家可以想想為什麽)。而在客戶端(JBOSS),PS對象會存在一個緩沖中(LRU鏈表),也就是說,這塊內存是事先配好的,
應用端內存的分配在conn.prepareStatement(sql)或都conn.CreateStatement(sql)的時候完成。
setFetchSize 最主要是為了減少網絡交互次數設計的。訪問ResultSet時,如果它每次只從服務器上取一行數據,則會產生大量的開銷。setFetchSize的意 思是當調用rs.next時,ResultSet會一次性從服務器上取得多少行數據回來,這樣在下次rs.next時,它可以直接從內存中獲取出數據而不 需要網絡交互,提高了效率。 這個設置可能會被某些JDBC驅動忽略的,而且設置過大也會造成內存的上升。
參看博文:
https://blog.csdn.net/bincavin/article/details/8727612
https://blog.csdn.net/hx756262429/article/details/8196845

2、Statement接口和ResultSet接口中setFetchSize(int rows)理解

1)Statement接口中解釋如下:
為JDBC 驅動程序提供一個提示,它提示此Statement 生成的ResultSet 對象需要更多行時應該從數據庫獲取的行數。指定的行數僅影響使
用此語句創建的結果集合。如果指定的值為 0,則忽略該提示。默認值為 0。
2)ResultSet接口中解釋如下:
為 JDBC 驅動程序設置此ResultSet 對象需要更多行時應該從數據庫獲取的行數。如果指定的獲取大小為零,則 JDBC 驅動程序忽略該值,
隨意對獲取大小作出它自己的最佳猜測。默認值由創建結果集的Statement 對象設置。獲取大小可以在任何時間更改。

3、優化查詢思路:使用spring的JdbcTemplate獲取數據源後再使原始setFetchSize方法

原spring集成ibatis後使用getList()進行查詢方法如下:
List org.biframework.dao.ibatis.BaseDao.getList(String statementName, Object parameterObject) throws DaoException

3.1)配置jdbcTemplate對象
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref local="dataSource"/>
</property>
</bean>
3.2)獲取JdbcTemplate對象

技術分享圖片
方法一:實現類(service)中利用構造器去獲取JdbcTemplate對象
<bean id="stPolicyService"
    class="org.bussiness.product.detailquery.service.StPolicyService">
    <property name="stPolicyDao">
        <ref local="stPolicyDao" />
    </property>
    <property name="jdbcTemplate">
        <ref bean="jdbcTemplate" />
    </property>
</bean>
同時在StPolicyService類中提供jdbcTemplate對象的set和get方法

方法二:Spring也我們提供了JdbcDaoSupport支持類,所有DAO繼承這個類,就會自動獲得JdbcTemplate(前提是註入DataSource)
<bean id="userDao" class="com.curd.spring.impl.UserDAOImpl">
    <property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
View Code

spring集成ibatis進行項目中dao層基類封裝可以參看我的博文:https://www.cnblogs.com/jiarui-zjb/p/9534810.html

3.3)點擊導出按鈕,生成Excle或者zip功能實現:
支持每個Excle文件最多15萬條數據,每個sheet頁最多5萬條數據,導出數據量小於等於15萬條則生成excle文件,大於15萬條將生成zip文件





參看博文:https://www.cnblogs.com/lichenwei/p/3902294.html

六、六、ibatis1.2.8查詢性能優化,實現百萬數據zip導出