ASP语言操作大记录集实践探究2.docx
《ASP语言操作大记录集实践探究2.docx》由会员分享,可在线阅读,更多相关《ASP语言操作大记录集实践探究2.docx(7页珍藏版)》请在冰豆网上搜索。
![ASP语言操作大记录集实践探究2.docx](https://file1.bdocx.com/fileroot1/2023-1/31/e6611a31-87d3-4a91-9b66-0389c4a520ff/e6611a31-87d3-4a91-9b66-0389c4a520ff1.gif)
ASP语言操作大记录集实践探究2
ASP语言操作大记录集实践探究
摘要
ASP语言作为较早被人用于服务器端交互式脚本编程的语言,已经在程序员中深入人心。
但是,随着人们对于交互式脚本编程的要求与日俱增,ASP也显示出他的一些局限性,特别是ASP在操作大记录集时的延迟问题,使得ASP语言目前已经濒临被服务器端交互式编程行业淘汰的危险。
本文重点研究如何解决ASP语言在操作大记录集时的延迟问题,并且提出了响应的解决方案,使得ASP在调整算法后,放弃了ADODB.RECORDSET中的内置分页方法,放弃了ADODB.RECORDSET.RECORDCOUNT属性和ADODB.RECORDSET.PAGECOUNT属性等内置的属性,对这些方法和属性进行了独立的开发,大幅度提高了ASP操作大记录集时的效率,从一定程度上解决了ASP语言操作大记录集时的延时问题。
关键词:
ASP语言;大记录集;延迟;改进;
ASP语言简介
ASP语言从早期的basic语言发展起来,是在目前分布式程序编写行业内最常用的脚本语言。
目前,市面上三分之一以上的分布式软件,是由ASP语言编写,特别是在微小企业使用的分布式软件中,都是由ASP写成。
现在,第一主机等国内知名的机房运营商都对外提供年管理费仅有一百余元的ASP+ACCESS的广域网虚拟空间。
同时,由于ASP服务器可以在安装了WINXP等家用操作系统的终端上,甚至包括笔记本电脑上安装,可以服务于整个公司的内部管理,所以ASP服务器成了目前市面上架设成本最为廉价的服务器。
ASP语言的局限性
ASP语言最大的局限性在于其执行速度和响应周期的问题上。
ASP语言的实质是一种脚本语言,他是一种没有经过编译的文本文件,系统如果要执行ASP程序,需要逐条读取ASP的文本数据到内存,然后进行逐条解释,再根据一个“伪环境”调用服务器资源进行执行。
这种执行方式与可以直接在服务器端编译的C#相比,响应速度的差距就不可同日而语了。
所以,使用ASP操作数千条的大记录集就成了痴人说梦的事情。
这也是制约ASP参与大型管理软件和大型论坛社区管理的一个不可逾越的鸿沟。
LIST.ASP面临的响应时间问题
ASP语言面临的最大的问题,是在LIST页的实现上。
根据教科书的方法,我们编写LIST.ASP时,需要从数据库中取出该LIST中需要显示的所有数据,然后使用ADODB.RECORDSET.PAGESIZE属性来对数据库中相关分页的数据做出分段。
这样一来,仅仅在调用rs.open就可能造成方法时,就可能发生脚本超时造成的宕机。
所以,传统方法使用ASP操作数据库,虽然没有官方的说明,但是在民间一般认为,记录集超过8000条时,ASP方案就会被PASS。
而目前绝大多数管理系统和论坛社区软件,记录集都远超过了8000条。
笔者曾经亲见在一个上市企业使用ASP制作的内部通知管理系统中,出现99秒的脚本响应速度,而当时这个系统的数据库记录量只有27000余条。
典型的LIST.ASP页面代码
这段代码是每一本ASP教程上都会出现的很典型的ASP示例代码,目前为止,绝大多数ASP程序员在编写LIST.ASP模块时,也都会沿用这段代码的基本结构,仅仅是根据排版要求,对代码进行简单的修改。
现在,我们利用注释的方式来逐一分析下这段代码的利弊。
<%
setconn=server.createobject("adodb.connection")
conn.open("DRIVER=DriverdoMicrosoftaccess(*.mdb);UID=admin;pwd=;dbq="&server.Mappath("1.mdb"))
‘开始的两句是连接MDB数据库,这两句是绝对的干练,也是基本上每一个ASP程序员都会写的两句。
这两句并没有什么不妥。
setrs=server.createobject("adodb.recordset")
sql="select*fromstudent"
rs.opensql,conn,3
‘这三句是建立查询和查询指针的代码。
本代码段的问题的根源就在这里出现了。
我们注意看这句查询语句,很明显是将STUDENT表中的所有信息建立查询,这样一来,我们就等于要使用这个RS指针来操作整个STUDENT表的数据。
rs.pagesize=20
ifrequest("page")<>""then
epage=cint(request("page"))
ifepage<1thenepage=1
ifepage>rs.pagecountthenepage=rs.pagecount
else
epage=1
endif
rs.absolutepage=epage
‘这段代码的主要目的,是调用ADODB.RECORDSET中的分页属性来将这个查询进行分页,每页显示20条记录,我们从自变量request(“page”)中得到需要当前显示的页码,然后分析出具体应该显示哪20条记录作为本次LIST的内容。
似乎如果要使用ASP来编写这个软件,那么这个算法是最精简的,但是,我们看到这段代码中,仅仅9行代码就调用了两次rs.pagecount属性,而调用一次这个属性,系统就会让RS指针将整个查询遍历一遍。
%>
<%=rs(0).name%> | <%=rs (1).name%> | <%=rs (2).name%> | 输出表头,这段写的中规中矩,虽然排版做的非常差,但是这毕竟是示例软件,我们不说什么。
>
<%
fori=0tors.pagesize-1
ifrs.boforrs.eofthenexitfor
%>
<%=rs(0).value%> | <%=rs (1).value%> | <%=rs (2).value%> | <%
rs.movenext()
next
%>
这一个20环的循环,也是这个LIST.ASP模块的核心。
虽然这一段代码我们说不出什么,但是,我们先关注一下这段,下一节我们会重点讨论。
>
<%
conn.close()
‘关闭数据库,ASP操作数据库必须的结尾操作。
%>
经典算法的改进要点
通过上述分析,我们知道,经典算法中最大的问题就操作了大量的无用的数据,因为我们最终输出给用户的,只是在中间部分20环循环中需要输出的数据。
LIST需要调用的数据库之外的数据,不管是几十条几百条还是几万条,都与LIST.ASP的功能没有太多的关系。
而ASP取数算法分为两个部分,一部分工作是使用脚本解释执行方式的ASP软件来完成,一部分工作是更贴近硬件的数据库环境来完成。
我们如果能将在海量的数据中取到我们需要显示的这20条数据的工作,交给更贴近硬件的数据库环境来完成,让ASP的任务简化成不论数据库的总记录数有多大,他只操作眼前的20条数据,那就从理论上可以直接解决ASP响应速度因为记录集的增大而显著变慢的问题。
直接分页取数FUCTION的编写
直接分页取数的算法,主要来自TOP和ORDERBY子句的配合。
我们首先从数据库表中取出第一条到目标数据最后一条之间的数据,然后将这组数据使用ORDERBYDESC子句反过来,然后取出我们需要的数据,再一次,我们只使用ORDERBY数据,将这组数据的顺序做最后的调整。
这样一来,我们就可以把分页和取数的工作交给响应速度较快的数据库去做,从而避免了ASP直接操作大记录集带来的时间延迟。
<%
fuctionsqlmid(listname,pagenum,pagesizes)
pagenum=cint(pagenum)
pagesizes=cint(pagesizes)
sql="select*from(selecttop"&pagesizes&"*from(selecttop"&(pagenum-1)*pagesizes+1+pagesizes&"*from"&listname&"orderbyid)orderbyiddesc)orderbyid"
setrs=server.CreateObject("adodb.recordset")
rs.opensql,conn,3
endfuction
%>
采用了新算法是LIST.ASP代码
这种方式,不仅仅在ASP+ACCESS的模式下可以使用,在ASP+MYSQL的模式下,以及在ASP+SQLSERVER的模式下都可以使用。
此项算法,在以往的实验中,可以将ASP处理大记录集的能力,提高到5万条以上,系统响应速度不超过3秒,综合考虑服务器成本的因素,在客户容忍的范围之内。
<%
fuctionsqlmid(listname,pagenum,pagesizes)
pagenum=cint(pagenum)
pagesizes=cint(pagesizes)
sql="select*from(selecttop"&pagesizes&"*from(selecttop"&(pagenum-1)*pagesizes+1+pagesizes&"*from"&listname&"orderbyid)orderbyiddesc)orderbyid"
setrs=server.CreateObject("adodb.recordset")
rs.opensql,conn,3
endfuction
‘使用了前节编写的FUCTION代码。
setconn=server.createobject("adodb.connection")
conn.open("DRIVER=DriverdoMicrosoftaccess(*.mdb);UID=admin;pwd=;dbq="&server.Mappath("1.mdb"))
‘连接数据库,跟之前代码没有什么变动。
callsqlmid(sdudent,cint(request(page)),20)
‘调用FUCTION。
%>
<%=rs(0).name%> | <%=rs (1).name%> | <%=rs (2).name%> | 输出表头,沿用了之前代码。
>
<%
Dowhilenotrs.boforrs.eof
%>
<%=rs(0).value%> | <%=rs (1).value%> | <%=rs (2).value%> | <%
rs.movenext()
loop
%>
这一个20环的循环,也是这个LIST.ASP模块的核心。
除了将for循环改成了dowhile循环,我们对这一节没有做什么改变,但是,我们可以看到,这次调用的这20条数据,是ASP在数据库中调取的全部数据。
>
<%
conn.close()
‘关闭数据库,ASP操作数据库必须的结尾操作。
%>
存在的问题和解决方法
因为本取数算法只建立LIST显示部分的数据,所以,ADODB.RECORDSET.RECORDCOUNT属性和ADODB.RECORDSET.PAGECOUNT属性就不能反映正确的数值,所以,在计算总记录数和总页数的时候,就面临着很大的缺陷。
应对这个缺陷,我们可以使用三种方式:
第一、根据在网页中只调用一次大记录集,读取相应的总记录数量值,随即将大记录集关闭。
这一步操作因为指针变量只需要遍历一遍大记录集,所以在5万条记录的情况下,只需要占用1秒左右的响应时间。
可以将ASP的响应时间控制在客户的容忍度之内。
第二、在服务器端设立独立软件,直接向application变量中写入总记录数的值,这样就不会占用用户访问的时间。
但是这样会存在一定的局限性,比如不能准确的反映LIST.ASP执行过程中的实际记录值,也对系统的稳定性提出了考验。
第三、在数据库中设立专门的记录来同步记录数据库的总记录数等数据,这样,比如,我们在日志模块中加入一个独立表,在客户新增和删除记录的时候,维护一个数据,这个数据准确的反映了数据库中的总记录数,这样,我们就不需要对这个总记录数使用大记录集的模式来在每一次访问时统计,就可以直接读出了。
动易ASP系统等知名的ASP软件都采用的这一种管理模式。
总结
ASP语言不能操作大记录集的现状是ASP中某个控件的先天不足的原因造成的,我们通过合理的调整ASP语言的算法,可以较完美的规避ASP语言在操作大记录集时的延迟过大以及宕机的问题。
虽然进行了这一步算法调整的ASP语言,仍然在操作大记录集的工作中比C#等语言要差的多,但是考虑到ASP服务器的架设成本优势,本算法调整可以使ASP语言在中小企业分布式软件和中小型论坛社区的编写工作中,重新焕发出他的光芒。
参考文献
[1]叶钰;刘永胜;李太宁.用ASP技术对记录集实现分页显示[J]泰州职业技术学院学报2006(08)135-137
[2]神龙工作室.ASP网站编程入门与提高[M]北京.人民邮电出版社.200735-127
*姓名
马源
性别
男
出身年月
19900920
籍贯
陕西宝鸡
学历
本科
毕业院校
软件设计测试
现有职称
研究方向
计算机科学与技术软件方向
单位名称
西安外事学院
*收刊地址及邮编;
陕西省西安外事学院北校区:
710077