同事在公司論壇里面發的,其實是我接手的一個項目中存在這個問題。
在使用Hibernate分頁器時,習慣使用直接把查詢語句、頁數、分頁大小,傳給分頁器,這樣會默認使用last來獲取總記錄數,效率非常的低。
解決方法,很簡單,就是用SQL來count查詢條件獲得總記錄的Query,再給Hibernate分頁器(本身就寫好了的)。
這樣就必須多寫幾行代碼,就是因為自己懶,覺著效果都一樣,就簡單的寫了。
數據量大了以后,就很明顯的速度慢下來了。又全部重頭改過,很是郁悶。
轉載此文,以示提醒!
即使懶得研究Hibernate底層,也要注意它的效率問題。
我看到一些資料這樣說,oracle的jdbc驅動是不支持服務器端的游標的,當你調用resultSet.last()時,jdbc驅動程序會把整個結果集的數據讀到內存,然后在內存中進行結果集的遍歷。
如果在做分頁的時候,用這樣的方式獲取結果的總記錄數:
rs.last();
int rowcount = rs.getRow();
在結果集很大的時候,這個性能是相當低下的,并且會用掉很多的內存。
這個問題是昨天在檢查人才網的代碼時發現的,隨著數據增加,原來被掩蓋的問題才開始暴露出來。我們用jprofiler對程序進行剖析的情況也間接的證明了上面的說法:1) 連續幾次刷新工作列表后,虛擬機的內存被占滿了,運行垃圾回收后內存又被釋放出來。2) 從頁面請求到完成響應,resultSet.last()方法的調用占去了cpu的絕大部分時間。
因為上面提到的分頁方法是一種常用的方法,我建議大家考慮一下自己的代碼是否存在這樣的問題,這對辦公系統的穩定運行可能是很重要的。
參考:
http://www.oracle.com/technology/global/cn/sample_code/tech/java/codesnippet/jdbc/rs/CountResult.html
提到了:
如果 ResultSet 非常大,則 resultset.last() 有可能是非常費時的操作,因為它將使用服務器端的更多資源。因此,除非確實需要可滾動結果集,應避免使用這種方法。
http://forum.springframework.org/showthread.php?t=50044&page=2
提到了:
Anyway, if it's a normal behaviour of the oracle driver to keep data in memory when using SCROLLABLE resultset
http://xiongbo.javaeye.com/blog/38481
對幾種游標類型做了介紹,并給出了建議
posted on 2008-05-28 11:26
rox 閱讀(4187)
評論(4) 編輯 收藏 所屬分類:
hibernate