Colorful Life2010

一种效率极高的ASP分页思想[ZT]
Weather:好晴朗啊....

  在ASP中显示大量数据时的翻页问题已经有不少文章介绍过了,一般情况下利用ADO页定位方法实现翻页功能。但随着数据库内容增多,翻页的效率问题就突出了,ADO的页定位方法速度明显地有些令人不能容忍。

  为了找到一种高效率的翻页方法,我分析了常见的几种ADO页定位方法,发现在翻页前都要利用查询语句把符合条件的纪录读出,放入RecordSet集合,然后再进行翻页的计算和操作。如果符合条件的纪录数大于你设定的每页显示纪录数,则多出来的纪录虽然已经读出但却没有用上,在翻到下一页时,又重新查询数据库。也就是说,如果你找到符合要求的500条纪录,查询时读出了500条纪录,但每页只显示20条纪录,这就有480条纪录读出后没用,翻页时又重复上述操作。众所周知,从数据源读取数据的操作是很费时间的,更何况读出来的数据大部份用不上呢?于是,我想如果每次只读出符合条件的、数量不超过每页显示条数的纪录应该是效率最高的,顺着这个思路又考虑到翻页所必需的条件,就产生了记住每页两端的记录号、翻页时只从端点读取每页显示条数的分页方法。

  由于接触ASP的时间不长,从思路到实现还有一段距离,故在一个论坛中提出了这个想法与大家讨论,经过该论坛版主和网友们的分析、建议和指教逐步完成了这段代码,在我的老PII机器上进行检测,效果比较明显。在此特详细思路、解决办法、代码贴出请各位高人指教。

一、原则
1.每次刷新页面时根据翻页的方向,只读取自id1或id2开始的rows条纪录。
2.显示查询结果时用for/next循环,不用where not rs.eof and i<=rows/loop循环,目的是在循环时不检验rs.eof以提高速度。
3.当纪录的序号不连续时也能正常完成翻页功能。

二、方法
1.数据表中建立一个自动编号字段ID用以识别纪录号。
2.第一次查询时读出所有符合条件的纪录,用以计算有多少页(max)和多少条纪录(num),以后查询时每次只读出rows条纪录,并且不做重复计算。
3.用sql语句的TOP rows格式来读出所需要的数据,翻页的主要工作在这里完成。
4.向前翻页时用降序排序的方法实现。
5.用url转移时带上每页的页号、两端的端点号、最大页数、最大纪录数。

  开始写代码的时候用过复合查询、升序排序等种种办法,结果均不理想,翻页经常翻到岔路上去,主要问题是如果用where ID<id1 则数据是从ID=0开始的rows条纪录,直接显示了第一页,没有达到向前翻页的目的;如果用降序排序,则数据是从ID<=id1开始的,但向后翻页的端点id2<id1,造成了混乱。当时直埋怨作系统的为何不来个Bottom N或Last N之类的指令,那就简单多了。试了几次后突然想到一个笨办法:既然是降序排序,在显示的时候反过来循环不就一切正常了?看来最简单的办法也可能是最有效的办法。另外,我认为除了用记忆端点分页的可以提高效率外,程序是否精炼,也会影响到速度。

这段代码没有考虑页面跳转的功能,我想除了论坛以外,如果是资料查询检索,页面跳转的用处不大,尤其是向后跳转。至于向前跳转,在代码中加入一些指令实现起来不难。

三、代码

------- 读取数据部分 -----------

id1,id2 - 页端点号,sn - 当前页号,sp - 上一页号, rows - 每页显示条数,go - 翻页方向(* 表示向回翻),max - 合计页数,num - 合计纪录数

[QUOTE]dim id1,id2,sn,rows,go,sql,max,num
sql="select * from 数据表 where 查询条件"
go=request("go")
sn=1
rows=10
id1=request("id1")
if id1<>"" then
sql=left(sql,6)&" top "&rows&right(sql,len(sql)-6)
if go="*" then
  sn=request("sp")-1
  sql=sql & " and ID<"&id1&" order by ID desc"
else
  sn=request("sp")+1
  id2=request("id2")
  sql=sql & " and ID>"&id2
end if
end if
Set Rs=server.createobject("ADODB.Recordset")
Rs.open sql,conn,3,1
if Rs.eof or Rs.bof then 提示没有纪录并返回 [/QUOTE]
------- 计算部分 -----------

[QUOTE]if id1="" then
num=Rs.recordcount
max=int(num/rows+0.99)
if max<1 then
  rows=num
  max=1
end if
else
max=int(request("m"))
num=request("n")
end if [/QUOTE]

------- 显示子程序 -----------

[QUOTE]sub show(i)
response.write 显示的内容
end sub

%>
<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>test</title>
</head> [/QUOTE]

------- 数据显示部份 -----------

[QUOTE]<body>
<div>
<p>有【<%=num%>】条信息,第 <%=sn%> 页 共 <%=max%> 页</p>
<hr size="1">
<ul>
<%
m=num-((sn-1)*rows)
if m>rows then m=rows
if go="*" then
Rs.movelast
id1=Rs("ID")
for i=1 to m
  show(i)
  Rs.moveprevious
next
Rs.movenext
else
Rs.movefirst
id1=Rs("ID")
for i=1 to m
  show(i)
  Rs.movenext
next
Rs.moveprevious
end if
id2=Rs("ID")
surl="test.asp?sp="&sn&"&m="&max&"&n="&num&"&id1="&id1&"&id2="&id2
rs.close
set rs=nothing
conn.close
set conn=nothing
</ul>
<hr size="1">
<table cellpadding="0" cellspacing="0" width="100%">
  <tr>
    <td width="80%"></td>
    <td width="10%"><%if sn>1 then response.write "<a href='"&surl&"&go=*'>上一页</a>"%>
</td>
    <td width="10%"><%if sn<max then response.write "<a href='"&surl&"'>下一页</a>"%>
</td>
  </tr>
</table>
</div>
</body>
</html> [/QUOTE]
四、测试对比

5万条纪录的Access数据库(大小为26.2M),用了几种方法分别进行运行时间测试,结果如下:

------------------------------------------
页号 |ADO页定位|Bookmark|list.asp|记忆端点
------------------------------------------
1  10.66   10.98  10.71  9.71
2  6.59     7.48  6.70   0.66
3  6.42     7.73  6.58   0.27
4  6.53    7.68  6.48   0.27
5  6.37    7.68  6.60   0.33
6  6.65    7.52  6.58   0.33
7  6.41    7.53  6.49   0.27
8  6.36    8.19  6.64   0.27
9  6.31    7.85  6.54   0.33
10  6.43    7.58  6.53   0.33
11  6.48    7.57  6.53   0.33
10  6.43    7.53  6.63   0.38
9  6.54    7.64  6.53   0.33
8  6.41    7.57  6.58   0.33
7  6.42    7.68  6.53   0.32
6  6.42    7.57  6.48   0.33
5  6.41    7.65  6.63   0.27
4  6.37    7.62  6.48   0.33
3  6.48    7.59  6.47   0.32
2  6.75    7.60  6.52   0.28
1  6.53    7.61  6.48   0.32
------------------------------------------
list.asp是论坛中ywd1520朋友提供的从动网里分离出来的分页程序,bookmark是某版主朋友提供的分页程序,时间单位:秒。

测试环境:
清除所有缓存文件,用相同的页面和查询条件,检索出5万条符合要求的纪录,顺序翻页,先向后再向前。每页10条纪录,每条纪录4个字段。
硬件配置:PII350超外频至133M使用,256M SDRAM内存,5.1G昆腾硬盘
操作系统:WinMe, PWS, MS Access2000

盼各位高人指教,谢谢。

[一种效率极高的ASP分页思想[ZT]]的回复

大雾 于 2004-08-28 20:23:35 发表 | IP:222.45.88.*
青蛙柠檬漆,哼哼偶新改的叶子http://www.blogcn.com/User7/joy_xiaozhu720/index.html这会应该避免一些失误咯~~~哼哼
柠檬园主 于 2004-08-29 12:14:14 发表 | IP:210.83.202.*
汗...我现在打不开呀.真想看看你到底改成啥样子了...
改好了的话,偶给你加上偶的链接里面去.
大大雾 于 2004-08-29 23:06:15 发表 | IP:222.45.89.*
哼~~好了才加~~假了吧~~RE同学都能打开,你能打不开吗?哼哼~~~~[em18]
4#   柠檬园主 于 2004-08-30 08:56:04 发表 | IP:210.83.202.*
好好,给你加上,小样儿,你上次的那个确实是太乱了,这次还好.不过我昨天也确实打不开,可能是我们的网不好昨天,嗯嗯,现在给小雾加上喽....
5#   re 于 2004-08-30 10:03:02 发表 | IP:218.79.253.*
你怎么知道我能够打开的?
我确实是去打开了,可是想留言需要先注册,我输了个帐号竟然说存在,就算了。
6#   大大大雾 于 2004-08-30 21:36:03 发表 | IP:222.45.89.*

哼~~互加哼哼互相学习嘿嘿~~
RE留的大名在上面瞎子都看的到~~何况偶不是瞎子
还有是不能中文留名字`~偶用的是最原始的博客,所以不搬家咯~~声明:俺是大雾!!!

7#   re 于 2004-09-10 17:12:19 发表 | IP:211.160.163.*
啊,我怎么没记得我留了言的呀。诶,再去仔细找找。
8#   littlenew 于 2007-07-13 17:12:31 发表 | IP:219.134.19.*

看一下这个问题能不能解决。

我不知道改动了什么服务 , 我的ASP程序只要改动一点,就必须得重启IIS,才能看到修改后的效果,这是怎么回事。急呀,

9#   柠檬园主 于 2007-07-13 23:49:05 发表 | IP:221.201.165.*

可能是你IE的选项里的Internet临时文件的设置有问题吧,是不是设置成了更新不检查了?

再不行把网站属性里的目录》配置》选项里的缓存的勾去掉。

10#   littlenew 于 2007-07-14 11:19:43 发表 | IP:61.141.202.*

这样好像也不行呀,我都试了一下,不知道怎么回事。真是郁闷,难道这样也要重装系统吗?

11#   littlenew 于 2007-07-16 11:32:51 发表 | IP:218.18.131.*

似乎是有点正常了,是卖咖啡的事。卸了。正常了。真的好晕呀。

12#   柠檬园主 于 2007-07-18 08:56:09 发表 | IP:59.44.76.*

哈哈,那是你的McAfee设置得不当了,我自己电脑用McAfee,服务器也用,都没事。

13#   littlenew 于 2007-07-27 08:47:18 发表 | IP:218.18.131.*

说实话,卖咖啡确实不错,我也不想换掉它,但我基本上没有什么配置,就是不行。,现在换了小红伞,感觉一般般,占内存特小。

14#   柠檬园主 于 2007-07-29 22:11:10 发表 | IP:221.201.145.*

可怜的McAfee呀...

Post a Comment~