現(xiàn)在項(xiàng)目的分頁是使用jdbc的 absolute的方法,設(shè)置Resultset為TYPE_SCROLL_INSENSITIVE。用了幾年,問題也不大,在幾個(gè)數(shù)據(jù)庫上都測試過,100萬條記錄一點(diǎn)問題沒有。

當(dāng)初曾經(jīng)查看過jdbc的文檔,確定數(shù)據(jù)只是在真正要取的時(shí)候才會(huì)從數(shù)據(jù)庫讀取, jdbc會(huì)根據(jù)fetch size的大小一次的預(yù)讀一部分記錄。

這幾天看的wicket的開發(fā)文檔和pojo in action都提到這種jdbc的讀取方式會(huì)有性能問題, 由不得我不測試一下。

先寫了一個(gè)最簡單的jdbc測試,在100萬記錄的情況下對(duì)數(shù)據(jù)庫進(jìn)行absolute定位操作, 從20萬開始取1頁記錄大約是5秒, 但是再往上面加,比如40萬開始就內(nèi)存溢出了。這就說明oracle的jdbc在用absolute的時(shí)候確實(shí)是要逐行讀取數(shù)據(jù)的。另外發(fā)現(xiàn),設(shè)置fetchsize ,速度會(huì)有10%左右的提高。

然后改用oracle 自身的 rownum的方式進(jìn)行分頁測試.

  SELECT * FROM (SELECT A.*, ROWNUM RN FROM (SELECT * FROM demo_table) A WHERE ROWNUM <= 200010WHERE RN >= 200000

 

執(zhí)行速度確實(shí)快了一些, 大約在2-3秒之間。但是這種方式應(yīng)該是越到后面越慢,果然從90萬位置開始取, 大約是在13秒左右。這樣一來,修改實(shí)現(xiàn)方式好像就是必須的了, 但是奇怪的是,使用ibatis的分頁并沒有什么內(nèi)存溢出的問題,100萬記錄到最后一頁,感覺上大概也是10多秒。

看了一下ibatis的queryForList這個(gè)方法, debug了一下, 發(fā)現(xiàn)他有個(gè)判斷, 對(duì)于forward_only的類型的resultset 是用循環(huán)next來定位的(記得以前自己的分頁實(shí)現(xiàn)里面為了兼容性也做了這樣的處理),而不是我誤以為的absolute方式。

看來oracle的jdbc 對(duì)于forward_only的resultset做 next方法是不會(huì)產(chǎn)生真正的讀取操作。 用jdbc 測試了一下,果真如此。 從90萬記錄開始取,沒有出現(xiàn)內(nèi)存溢出的問題,執(zhí)行時(shí)間大約22秒左右。

不知道這種差別在mysql和db2上是否也是如此,下次有時(shí)間再做一個(gè)測試看看。

至于next和rownum執(zhí)行效率的差距, 我估計(jì)是前者必須用游標(biāo)順序定位。

現(xiàn)在的問題就是, 兩者比較, 執(zhí)行時(shí)間只相差一倍而已,還是一個(gè)數(shù)量級(jí)別的,就為了這個(gè)做修改,還導(dǎo)致sql不可以跨數(shù)據(jù)庫,好像一點(diǎn)都不值得。甚至如果用戶不直接翻到最后幾頁,根本感覺不到速度差別。
 
后來想想,老外有時(shí)候也是腦子壞了, 什么樣的項(xiàng)目會(huì)需要你沒事去翻上百萬記錄。還是保持原狀,丟在哪再說吧

測試環(huán)境:oracle9i 2版, 西文字符集。沒對(duì)其他參數(shù)進(jìn)行測試。