Access分頁方案
開門見上,本文主要是回答一下三個問題:
- Access是否存在更有效率的分頁方法?
- 現(xiàn)有Access大數(shù)據(jù)量10萬條數(shù)據(jù)分頁的效率測試
- Access的數(shù)據(jù)承載量到底有多大?
相信很多ASP的站點還在使用Access數(shù)據(jù)庫,因為Access數(shù)據(jù)庫無須開專門的數(shù)據(jù)庫空間,調(diào)用,遷移也方便,節(jié)省費用。另外對網(wǎng)站搭建者的專業(yè)能力要求也相對低一些。但隨著網(wǎng)站的運行,數(shù)據(jù)庫體積越來越大,數(shù)據(jù)量也從最初的幾百條到了現(xiàn)在的上萬條,上十萬條甚至更多。于是因數(shù)據(jù)應用級別的改變帶來的各種各樣的應用問題出現(xiàn)了。而其中大數(shù)據(jù)量的列表分頁效率問題更是讓很多人頭疼。筆者隨便通過“大數(shù)據(jù)量分頁效率”,“Access 分頁”等關(guān)鍵詞分別百度和谷歌了一下,發(fā)現(xiàn)有此疑問的大有人在。很多網(wǎng)頁上也給出了不同的解決辦法。那么,這些方法到底能達到優(yōu)化效率,提高速度的目的嗎?
先讓我們來看看以下的幾個Access分頁優(yōu)化方案,當然如果你直接將數(shù)據(jù)庫升級到SQL Server,那么有更好的諸如存儲過程等方法。今天我們就討論一下Access大數(shù)據(jù)量優(yōu)化分頁方法,以及Access到底能承受多少數(shù)據(jù)量。
方案一:利用ado本身的結(jié)果集的pagesize,AbsolutePage的屬性來進行分頁
程序示例:(僅供示意,完善的各種條件判斷自行添加)
- MaxPerPage=20
- page=cint(request("page"))
- sql="select * from 表 where 條件 order by 排序條件"
- set rst=server.CreateObject("adodb.recordset")
- rst.open sql,conn,1,1
- rst.pagesize=MaxPerPage
- rst.AbsolutePage = Page '將記錄定位到對應頁數(shù)的第一條
- for i=1 to MaxPerPage 循環(huán)列表
- rst.movenext
- if rst.eof then exit for
- next
這個方法是最為常用的Access分頁方法。
缺點:每次都要讀入符合條件的所有記錄,然后再定位于對應頁的記錄。當數(shù)據(jù)量大的時候,效率就十分的低下。
與此相似的方法是利用ado的move方法,每次將記錄集游標移動 (page-1)*pagesize ,就實現(xiàn)了了記錄的分頁。經(jīng)過測試,效率與方案一大致相同。
方案二:
1.設(shè)置一個自增長字段.并且該字段為INDEX.
2.由于是 Access ,所以,只能是前臺分頁.自增長字段目的,就是為了實現(xiàn)分頁功能.
1> 記錄用戶前頁的最后一個 自增值 ,例如 M .
2> 下一頁,取下一頁的開始值.M+1 ,結(jié)束值: M+1+1.5*PAGESIZE (注:由于數(shù)據(jù)庫會有增刪操作,故應該取頁大小應該有一個系數(shù),你可以根據(jù)情況自定一個1大的系數(shù).
3> 前臺循環(huán)取 RS 的前 PAGESIZE 條, 寫到一個 新的RS中,并返回.
這個方案通過自增值來分部截取不同分頁的數(shù)據(jù)列表,文中考慮到數(shù)據(jù)庫有增刪操作,所以加入了一個系數(shù)的概念,這是一個不得已的做法。這個方案可以保證分頁效率,但只能運用于增刪不太頻繁(自增值字段相鄰記錄的值相差不多的情況)的數(shù)據(jù)表。
方案三:not in 方法。
這個方案在很多網(wǎng)站上都轉(zhuǎn)載。據(jù)說對于越往前的分頁效率提高越明顯。我一直有所懷疑,因為“not in”本身就是個耗費資源的算法。很難相信一個低效率的方法能提高大數(shù)據(jù)量分頁的效率。示例如下:
- sql="select top 12 * from 表 where Id not in(select top page*pagesize Id from 表 order by id desc) order by Id desc"
如果是第9頁,每頁20條即
- select top 20 * from 表 where Id not in(select top 9*20 Id from 表 order by id desc) order by Id desc
原理即:選擇top 20 的記錄,條件是id不在前面分頁的記錄ID里。通過這種方式過濾掉前面分頁的記錄,然后通過top高效率的方式獲取當頁的記錄。
“top”確實高效,但是“not in”呢?
于是我直接用這種方法測試了一下,測試條件:10萬條數(shù)據(jù)。點擊查詢.......... MY GOD,長時間無響應,最后Ctrl+Alt+Delete 結(jié)束任務。再試,結(jié)果同樣如此。于是改變一下測試條件,變成1000條數(shù)據(jù),OK,結(jié)果顯示非常順利。
結(jié)論:如果你是大數(shù)據(jù)量分頁,還是不要用這種方法,會死人的。
方案四:
- "select * from (select top "&pagesize&" * from (select top "&page*pagesize&" * from 表" order by id desc) order by id) order by id desc"
這個方法簡單說來,就是選取當前頁及小于當前分頁的所有記錄,再通過“Top”方式選取當前頁的記錄。
這個方法沒有出現(xiàn)效率低的語句,雖然至少要select兩次(示例select了三次是為了排序)。但是效率應該不錯。且越靠前的分頁應該越明顯。
如果還想節(jié)省效率,可以只select兩次。
假如記錄ID為1-100,每頁5條?,F(xiàn)在顯示第4頁,排序為倒序。
執(zhí)行順序:
1) 選擇前4頁的數(shù)據(jù),即100-81共20條數(shù)據(jù)
2) 從這20條數(shù)據(jù)中選擇最小的5條,即81-85。
3) 將選擇的5條按倒序排,即成為 85-81。
如果節(jié)省第三步也可,只不過顯示變成
第一頁:96,97,98,99,100
第二頁:91,92,93,94,95
其實也不錯。
光說沒用,最終看測試結(jié)果。我在相同的數(shù)據(jù)條件,服務器配置下,分別對方案一中的兩種方法和方案四進行了Access分頁效率測試,測試數(shù)據(jù)如下
測試條件:
>10萬條;pagesize=20;
分頁總數(shù)>5000頁;
順便也進行了一下“select 部分字段”和“select 所有字段”的對比測試。
從上面的測試結(jié)果來看,方案三的優(yōu)勢還是比較明顯的。而到5000頁的效率基本上和前兩種方法差不多,甚至仍然有一定得優(yōu)勢。
另外,很多人在寫select語句時, 習慣 select * from 表,這不是一個好習慣。上面的Access分頁測試結(jié)果表明,還是按需索要,按需供應的好,需要什么字段,就select什么字段。能夠極大的節(jié)省服務器資源。
很多網(wǎng)友提到Access時都不免的輕視,“你還在用Access?”,“還不換SQL Server?”,“用Access你還想多快?”。其實在我的經(jīng)驗看來,即便是在10萬條的應用級別上。Access常常比SQL Server快。因為SQL Server需要額外連接,且多了一個帶寬連接因素的影響(當然,網(wǎng)站服務器和數(shù)據(jù)庫服務器運行速度和帶寬都很OK,那沒話說)。
SQL Server 在更高數(shù)據(jù)級別上的速度優(yōu)勢還是比較明顯,畢竟與Access不是一個級別的產(chǎn)品。
為了探索一下Access數(shù)據(jù)庫的極限。在40萬條數(shù)據(jù)的情況下進行了上述分頁測試。速度確實大打折扣。但是第三種方案在一萬頁內(nèi)還是表現(xiàn)不錯的。此時數(shù)據(jù)庫已經(jīng)達到400多兆。再結(jié)合之前處理過的幾個4,500兆的Access數(shù)據(jù)庫。我認為40萬條數(shù)據(jù)是Access數(shù)據(jù)庫在一般應用的一個界限,但不是極限。超過這個數(shù),就需要在程序優(yōu)化上做太多的工作。就有些不太值了。
原文鏈接:http://www.cnblogs.com/huanghai/archive/2011/03/19/1988627.html
【編輯推薦】