數(shù)據(jù)分頁(yè)方法新思路,速度10分快
發(fā)表時(shí)間:2024-01-22 來(lái)源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]這篇文章要達(dá)到的目的就是,實(shí)現(xiàn)大數(shù)據(jù)分頁(yè)瀏覽并最優(yōu)化速度。 建立一個(gè)web 應(yīng)用,分頁(yè)瀏覽功能必不可少;這個(gè)問(wèn)題也是長(zhǎng)久以來(lái)最普遍的問(wèn)題,目前也得到了較好的解決,其中象ASP 程序的分頁(yè)算法有很多,比如使用ado 對(duì)象的PageSize 這些屬性,按記錄總數(shù)計(jì)算頁(yè),然后跳轉(zhuǎn)記錄集再輸出;也有編寫(xiě)存...
這篇文章要達(dá)到的目的就是,實(shí)現(xiàn)大數(shù)據(jù)分頁(yè)瀏覽并最優(yōu)化速度。
建立一個(gè)web 應(yīng)用,分頁(yè)瀏覽功能必不可少;這個(gè)問(wèn)題也是長(zhǎng)久以來(lái)最普遍的問(wèn)題,目前也得到了較好的解決,其中象ASP 程序的分頁(yè)算法有很多,比如使用ado 對(duì)象的PageSize 這些屬性,按記錄總數(shù)計(jì)算頁(yè),然后跳轉(zhuǎn)記錄集再輸出;也有編寫(xiě)存儲(chǔ)過(guò)程實(shí)現(xiàn)分頁(yè)數(shù)據(jù),這些方面各有優(yōu)缺點(diǎn),以下本人介紹一種應(yīng)用實(shí)際項(xiàng)目中速度非常快的分頁(yè)算法;
關(guān)鍵點(diǎn):SQL (用TOP 和 自動(dòng)編號(hào) 實(shí)現(xiàn))
頁(yè)面腳本 (瀏覽器回退功能)
環(huán)境:
IIS/SQL Server/Access
表結(jié)構(gòu):
create table 內(nèi)容表 (
自動(dòng)編號(hào) IDENTITY(int, 1,1) not null,
分類(lèi)編碼 varchar(20) null,
標(biāo)題 varchar(255) NULL,
內(nèi)容 varchar(4000) null,
時(shí)間 datetime null,
)
實(shí)現(xiàn)原理:
這個(gè)表設(shè)定了自動(dòng)編號(hào)字段,這個(gè)字段的特性就是生成不重復(fù)的整形,包括刪除了記錄后該字段仍然保持‘流水性’(注:通常在系統(tǒng)表建設(shè)中,這種字段的運(yùn)用很少,因?yàn)榫幪?hào)不能自由管理,但在這里使用它,主要是想在文章中省略編號(hào)維護(hù)的代碼)。
分頁(yè):
那么第一步,就是查詢(xún)一個(gè)頁(yè)的數(shù)據(jù);如果有100筆記錄,按20記錄一頁(yè),那么通常的分頁(yè)算法就是“頁(yè)總數(shù)=總記錄 除 分頁(yè)的控制數(shù) [有余數(shù)的話(huà),頁(yè)總數(shù)加一]”,這樣的做法就導(dǎo)致必須產(chǎn)生所有記錄的一個(gè)大記錄集;從而,又有人提出了用存儲(chǔ)過(guò)程的分頁(yè)算法,前者是asp 腳本產(chǎn)生大記錄集,這樣速度相當(dāng)慢,后者是殺雞用牛刀,雖然我經(jīng)常寫(xiě)存儲(chǔ)過(guò)程,但根據(jù)我的思路會(huì)發(fā)現(xiàn)寫(xiě)存儲(chǔ)過(guò)程完全多余。
在SQL 中,許多剛接觸它的朋友都知道 Top 修飾關(guān)鍵字的作用;例如:select TOP 1 * from table1 --這樣就實(shí)現(xiàn)從Table1表返回只有一條記錄的記錄集那么分頁(yè)優(yōu)化的最終目的就是避免產(chǎn)生過(guò)大的記錄集,通過(guò)TOP 即可完全控制;現(xiàn)在查詢(xún)表應(yīng)該是 select Top 20 自動(dòng)編號(hào),標(biāo)題,內(nèi)容,時(shí)間 from 內(nèi)容表。
但現(xiàn)在還有個(gè)問(wèn)題,就是如何定位,Top 不可能自動(dòng)給我們定位輸出某個(gè)頁(yè),這就設(shè)計(jì)到了where 從句,根據(jù)一個(gè)特定條件輸出正確的內(nèi)容;注意:記錄的 order by 排序是非常重要的,這個(gè)決定了這個(gè)算法的成敗;
這里的演示是DESC 方式,倒序排列,比如網(wǎng)站的軟件更新,就是最近的更新放最前面,而這個(gè)就是倒序方式。
OK,下面來(lái)看看實(shí)際代碼,首先要確定是否為起始頁(yè)。
dim strSQL,i,endID,isBeginPage
const Cnt_PageSize = 20 '定義每頁(yè)記錄的大小
'通過(guò)檢查瀏覽器傳遞的Page 參數(shù)的值來(lái)判斷是否為進(jìn)入下一頁(yè)的操作
isBeginPage = isEmpty(request("Page")) or request("Page")="" or request("Page")<>"next"
'這里是分頁(yè)的核心
if isBeginPage then '如果是起始頁(yè)
'查詢(xún)=列出分類(lèi)編碼等于參數(shù)flbm 的記錄,按倒序排列,并只列出前 Cnt_PageSize 筆 (Cnt_PageSize是常量定義,比如20)
strSQL = "select TOP " & Cnt_pageSize & " 自動(dòng)編號(hào),標(biāo)題,內(nèi)容,時(shí)間 from 內(nèi)容表 where 分類(lèi)編碼= '" & TRIM(SQLEncode(request("flbm"))) & "' order by 自動(dòng)編號(hào) desc"
else '如果不是起始頁(yè)
if request("Page")="next" then '這里這樣寫(xiě)是為了加強(qiáng)代碼的表現(xiàn),如果參數(shù)為next ,則表示取下頁(yè)內(nèi)容
'查詢(xún)=列出分類(lèi)編碼等于參數(shù)flbm的記錄并且要小于自動(dòng)編號(hào)endID (endID也是參數(shù)),并倒序排列,并只列出前 Cnt_PageSize 筆 (Cnt_PageSize是常量定義,比如20)
strSQL = "select TOP " & Cnt_pageSize & " 自動(dòng)編號(hào),標(biāo)題,內(nèi)容,時(shí)間 from 內(nèi)容表 where 分類(lèi)編碼= '" & TRIM(SQLEncode(request("flbm"))) & "' and 自動(dòng)編號(hào)<" & request("endID") & " order by 自動(dòng)編號(hào) desc"
End if
end if
'打開(kāi)數(shù)據(jù)連接執(zhí)行SQL 并建立記錄集
set rs = Cnn.Execute(strSQL)
if not rs.Eof then '這里寫(xiě)入判斷是否為Eof 可以不要,但是,在這里卻有它的特殊意義
call TableTitle '這里是自寫(xiě)的函數(shù),用于建立表格標(biāo)記
call beginTr '這里是建立表格tr標(biāo)記
for i=0 to rs.fields.Count-1 '遍歷記錄集字段
call AddCol(rs(i).name) '輸出字段名
Next
call endTr
while not rs.eof '循環(huán)記錄集內(nèi)容,并輸出
call beginTr
for i=0 to rs.fields.Count-1
call AddRow(ASPEncode(rs(i).value))
Next
call endTr
endID = rs("自動(dòng)編號(hào)") '這里保存每次輸出的自動(dòng)編號(hào)值
rs.MoveNext
Wend
call TableBottom '到此為止,就簡(jiǎn)單的將記錄集內(nèi)容全部輸出
'這里輸出翻頁(yè)標(biāo)記,vbaIIF 是自寫(xiě)函數(shù)
原型為 function vbaIIF(a,b,c)
if a then
vbaIIF =b
else
vbaIIF =c
end if
end function
上一頁(yè)的實(shí)現(xiàn)是通過(guò)腳本調(diào)用瀏覽器的功能 history.back(1) 實(shí)現(xiàn),那么回頁(yè)時(shí)并不需要在服務(wù)器端重新生成數(shù)據(jù),速度不用考慮了。
在首頁(yè)的時(shí)候,上一頁(yè)的鏈接應(yīng)該是無(wú)效的,通過(guò) vbaIIF(isBeginPage,"disabled","") 實(shí)現(xiàn),如果為首頁(yè),那么在標(biāo)記中加入 disabled 屬性 ,如果不是首頁(yè),則加入history.back(1); 腳本指令,用于回退瀏覽頁(yè)。
下一頁(yè)是傳遞Page 參數(shù)和endID參數(shù),Page 設(shè)置為 next 表示為下一頁(yè)的動(dòng)作,endID 表示當(dāng)前記錄集的末尾編號(hào),下頁(yè)將由此分頁(yè)。
response.Write("〈a href=""#"" onclick=""
javascript:" & vbaIIF(isBeginPage,"","history.back(1);") & """ " & vbaIIF(isBeginPage," disabled ","") & "〉上一頁(yè)〈/a〉 〈a href=""TypeOptions.asp?flbm=" & request("flbm") & "&Page=next&endID=" & endID & """〉下一頁(yè)〈/a〉")
else
'這里通過(guò)判斷記錄集是否為空來(lái)解決到末尾頁(yè)還可以繼續(xù)翻頁(yè)的問(wèn)題
if not isBeginPage then
'判斷是否為空記錄,并且不是起始頁(yè),那么生成回退頁(yè)面的腳本,效果就是進(jìn)入該頁(yè)后將自動(dòng)返回到上頁(yè)。
response.Write "〈Script language=javascript〉" & vbCrlf
Response.Write "history.back(1);" & vbCrlf
Response.Write "〈/script〉"
Response.End
else '如果是起始頁(yè)記錄就為空,則提示無(wú)內(nèi)容
Response.Write "〈font color=blue〉該類(lèi)別下無(wú)內(nèi)容〈/font〉"
end if
end If
總結(jié):通過(guò)前臺(tái)腳本,SQL查詢(xún)技巧,實(shí)現(xiàn)高性能的分頁(yè)程序簡(jiǎn)單快速
希望同行提出更優(yōu)秀實(shí)時(shí)數(shù)據(jù)分頁(yè)算法
備注:由于論壇限制了HTML字符,所以關(guān)鍵符號(hào)采用了中文大寫(xiě)。