对于网络应用程序来说,性能是每个开发人员都应该关心的问题。性能的优劣直接影响网站能够正常运行,在网站访问量很大的时,如果网应用程序的性能欠佳,就会导致用户访问超时或者打不开页面,更严重时还会让整个服务器崩溃。本讲介绍一些关于优化ASP程序性能的基本知识。
本讲要点:
*ASP程序的代码优化
*数据库优化
*网页优化
1 ASP程序的代码优化
在使用代码编写应用程序的过程中,同一个功能可以使用不同的函数、不同的语法实现。但是不同的代码页会造成程序运行的效率不同,代码优化就是找到并消灭那些影响程序运行速度的代码。
1.1尽量减少对Session对象和Application对象的使用
虽然Session对象和Application对象对ASP变成具有很重要的作用,但是由于大量使用这两个对象会增加系统内存的开销,因此如果不合理地使用Session对象和Application对象就会降低系统的性能。
没有固定的模式规定什么数据应该使用Session对象存储,什么数据应该使用Application对象存储,存储数据的对象要根据实际情况确定。通常情况下,Session对象中的数据是每个用户使用的状态信息,如用户名。Application对象中的数据是所有用户的公共信息,只有所有用户都经常访问的信息才会存储到Application对象中,如数据库的连接。
1.2 及时关闭不使用的对象
不仅是ASP程序,所有应用程序都应该及时关闭不使用的对象。如果不及时关闭没有使用的对象,大量的对象就会长时间占用系统资源,导致系统运行缓慢。只有及时关闭不使用的对象才能回收系统分配出去的资源,提高系统的性能。
使用Session对象时,如果用户30 min(分钟)内没有任何操作,系统就会自动触发Session_OnEnd事件关闭Session对象。但是假如有大量的用户频繁的读取服务器,服务器在这段时间内仍然会保持那些已经没有用的Session对象。大量的Session对象会增加系统内存的开销,如果不及时关闭使用完的Session对象,就会降低系统的性能。
另外连接数据库也是一项非常耗费系统资源的工作。对于数据库的操作最佳方案是,尽量在一次数据库连接中处理所有的操作。使用完的Recordset对象要马上赋Nothing值,将不用的数据库连接立即关闭。
1.3合理使用Include文件
在ASP文件中,可以使用语句形式包含其它的文件。这些Include文件也是ASP程序,它把自己的公共函数放到包含它的文件中,供包含它的文件调用。
因为服务器端应用程序会对文件进行预编译,所以建议不要在一个文件中包含过多的Include文件。如果一个文件包含上百个Include文件,但它只使用其中的一个或几个函数,就会造成大量的函数被加载而未被使用,浪费系统的资源。
因此在一个文件中尽可能只放入相同类型的Include文件,这样既有利于函数的查找,又可以减小Include文件的大小。
1.4尽量使用系统函数代替自己编写的函数
想要实现一个功能时,不要急于编写代码,应该先看看开发平台是否又现成的函数能够实现想要的功能。如果有可以使用的函数,不仅免去了开发的烦恼,节省了开发时间。更重要的是,在大多数的情况下系统提供的函数比自己编写的函数性能好。
例如,使用VBScript脚本语言,分割一个有规律的字符串(“ggg,sss,aaa,bbb,mmm”),如果使用自己编写的函数既浪费时间,运行速度又慢。而使用系统提供的分割字符串函数split可以直接完成这个功能。
1.5减少动态数组的使用
如果读者学习过数据结构,一定会知道在动态数组中查找一个元素(即取动态数组中一个元素的值)要比在静态数组中慢。虽然在某些情况下动态数组是必不可少的,例如,对于数组存储的数据条数不确定的情况下,或是对数组中的元素访问量不是很大时,应该使用动态数组。但是对于存储的数据条数相对稳定,或时经常访问数组中的元素时,还是应该使用静态数组。
1.6养成提前声明变量的习惯
在脚本语言中,允许不声明变量而直接使用它。虽然这样编写代码会很方便,但是这是一种不好的习惯。在应用程序使用变量时,解释器会对变量进行处理。如果提前声明变量,会加快解释器执行的解释时间。如果变量不提前声明,不仅使程序代码难以阅读,还会使程序的执行效率大大降低。
如果读者还没有养成提前声明变量的习惯,建议在每一个ASP文件的开头加上”Option Explicit”语句。它可以在当前的文件中,强制要求显示声明代码中的所有变量,如果存在没有声明的变量,它就会报错。
1.7减少Response.writ的使用
下面的量个实例完成了相同的页面输出功能,但是通过运行可以知道第一个实例比第二个实例的速度要快。这是因为第二个实例在执行时增加了服务器的解释时间,因此降低了它的性能。
实例一:
<%
Dim ok
if ok=1then %>Hello World!
<%end if%>
实例二:
<%
Response.write “”
Response.write “”
Dim ok
If ok =1 then
Response.write “Hello World!”
End if
Response.write “”
Response.write “”
%>
1.8使用一个ASP文件完成一个操作
很多人喜欢在一个ASP文件中完成诸如添加、删除、查找等多个不同操作。不要以为这样做会充分地利用文件,这样做的结果只能使应用程序的运行速度减慢。
因为随着文件的增大,解释器的解释时间也会增长。只有将添加、删除、查找等操作分割成单个的、独立的ASP文件,才能使得文件不会过于庞大,降低服务器端解释器的负担。
1.9尽量使用Server.Transfer代替Response.Redirect
Response.Redirect的功能是让浏览器重新定位到另一个页面,即把浏览器得请求发送到另一个页面。常常使用这个函数把用户得请求重新定位到一个登陆页面或错误页面。由于请求强制重定位到新页面得操作,需要浏览器必须从Web服务器往返两次,因此Web服务器必须比常规多处理一个请求,并且增加了一个没有必要得往返过程。
IIS5.0以后得版本引入了一个新的函数Server.Transfer,它可以将所有操作转移到同一台服务器上的另一个ASP页中。这样就可以避免多余的服务器到浏览器,再由浏览器到服务器的往返过程,从而改善了系统的总体性能,缩短了用户的响应时间。
对于那些不需要重新定向,而只需要转移页面的情况,建议选择Server.Transfer函数完成。
1.10对URL地址进行编码
在使ASP程序动态生成一个带参数的URL地址并进行跳转时,IE浏览器对其会正常解析,但NetScrpe浏览器对其解析时会产生如下错误:
HTTP Error 400 400 bad Request Duo to malformed syntax,the request could not be understaood by the server.The client should not repeat the request without modifications.
解决这种错误的方法是,使用Server对象的URLencode方法对生成的URL地址参数进行URL编码。
1.11在循环中避免进行字符串连接
许多程序员习惯在循环语句中建立字符串,其实这不是一个好的处理方法,采用这种方法会出现一些问题。
反复串联字符串需要花费大量的时间,运行这种结构的循环语句所花费的时间与记录数乘以字段数所得值的平方成正比。
下面通过一个简单的实例说明这个问题,其代码如下:
S=””
For i=asc(“A”) to asc(“Z”)
S=s+chr(i)
Next i
上面的实例的处理过程为:在第一次循环中,获得了只有一个字符的字符串”A”。在第二次循环中,ASP程序必须重新分配字符串并将两个字符(“AB”)复制到s中。在第三次循环中,它还必须再次重新分配s并将三个字符复制到s中。这样在第N次循环中,它必须重新非陪并将N个字符复制到s中。总共就是1+2+3+…+N次,即N*(N+1)/2次复制。可见在循环中进行字符串连接是多每可怕的一种资源消耗。
如果在ASP程序中连接字符串,建议使用+=运算符,即使用s+=”某字符串”,而不使用s=s+”某字符串”。
1.12避免使用Request(”name”)的方式获得参数值
ASP支持使用Request(”name”)的方式获得参数的值,这样做的却很方便,但是带来方便的同时它页增加了系统的开销。
因为使用Request(”name”)的方式获取参数时,解释器并不知道要从哪个集合中来取值,于是它只能顺序搜索全部可能的集合:QueryString集合 、Form集合、Cookie集合、ClientCertficate集合和ServerVarible集合直到发现第一个匹配的名称为止。这样做比直接访问指定集合的效率要低许多。
这样做的另一个弊端时造成系统安全,因为当两个集合中都存在相同名称的值时,很有可能取到的值不是自己想要的。
2数据库优化
连接数据库,对于数据库中的数据进行操作是一项非常耗费系统资源的工作。数据库优化就是为数据库操作找出最佳方案。
2.1不要随便使用”select * from”语句
如果不是想要获取数据表中的所有字段,在使用select查询语句时,就不要使用”select * from”格式的语句。虽然使用这种格式的查询语句获得的查询结果不会遗漏任何字段,但正是因为它把大量没有用的数据从数据库中提取出来,造成系统的效率降低。
实际证明在select * from语句中,指明字段提取数据的方式,比使用”select * from”方式的速度要快5%左右。
2.2尽可能使用数据库中的存储过程
既可以使用在程序代码中编写SQL语句的方式完成数据库操作,也可以使用在数据库中编写存储过程,然后通过程序调用存储过程的方式完成数据库操作。这两种方式完成的工作是相同的,但是他们执行的效率是不同的。因为使用数据库中编写的存储过程,可以免去将程序中的SQL语句传输到数据库的过程。所以这种方式比在程序代码中编写SQL语句的方式快很多。
此外在数据库中编写存储过程的方式,把对数据库的所有操作都封装在数据库中,可以提高系统的安全性。
2.3注意游标的使用方法
如果只想读取数据库中的数据或者遍历表中的所有记录,使用forward-only,read-only游标就已经足够了。即使在读取很大数据量的数据时,使用这种游标都是最快速的。
2.4不要打开无用的独立记录集
会有人打开没有用的记录集吗?当然会有。例如,在生成一个树行记录集时,不仅要打开需要的记录集,还不得不打开它的父记录集、它的子记录集,甚至还会打开它的孙记录集。其实可以使用ADO提供的Data Shaping技术,这种技术会替代打开多个独立的记录集,加快程序的运行速度。
2.5及时关闭打开的记录集对象及连接对象
有些ASP程序最初运行的速度很快,但是运行随着运行次数的增多,速度就变得越来越慢,甚至出现服务器死机的情况。这种情况的发生很可能是因为打开太多的记录集对象或连接(Connection)对象,在使用后没有关闭它们引起的。
数据库连接是非常耗费资源的对象,在数据库操作完成后我们应当使用以下的方法关闭数据库连接。
Recordset.close
Set Recordset=nothing
Set Connection=nothing
2.6比较取得记录集中数据的方法
一共有四种方法可以取得一个记录集中某个字段包含的数据。下面分别是他们的语法格式。
Recordset(“字段名称”)
RecordSet(“字段名称”).Value
RecordSet(”字段序号”)
Set 方法
这四种方法的执行速度时不同的,其中Set方法最快,其次是Recordset(”字段序号”)方法,再次是Recordset(”字段名称”).Value方法,最慢的是Recordset(”字段名称”)方法。
下面介绍Set方法实例。
Dim strSQL
StrSQL=”select name, sex, age from yourtable”
Dim rs
Set rs=server.createobject(”ADODB.RECORDSET”)
Rs.open strSql, conn,1,1
Const fieldsOrder=2
Dim objOrder
Set objOrder=rs(fieldsOrder)
Response.write objOrder ‘Set方法
2.7使用字符串建立SQL查询
使用字符串建立数据的查询不仅不能加快服务器的解析速度,反而还会增加服务器的解析时间。但是本书仍然推荐使用字符串代替简单的查询语句进行查询,这样可以方便查找应用程序出现的问题,从而迅速地完成程序编码工作。
例如,在进行条件选择时,尽量使用case语句,避免使用if语句。使用case语句可以使程序流程化,执行的速度也比if语句快。
2.8 where语句中表之间的关联条件放在后面
前面我们已经介绍Where后面的条件语句是平等的。但是在实际使用过程中,如果Where后面的条件语句时对数据库的查询畜力 ,因为条件语句的顺序不同,会造成应用程序的执行效率不同。
例如,有两条执行SQL查询的语句,如下所示:
”Select Student.Name, Class.Name From Student,Class wher Student.ClassId=Class.Id And Student.Age >20”
”Select Student.Name, Class.Name From Student, Class Where Student.Age>20 And Student.ClassId=Class.ID”
第一条语句先将Student表中所有的记录同Class表中所有的记录进行匹配,然后再筛选出Student.Age大于20的记录。而第二条语句先筛选出Student.Age大于20的记录,然后再将筛选出的记录同Class表中的记录进行匹配。虽然这两条语句都会得到相同的结果,但是由于第二条语句需要匹配的记录数比第一条语句少,因此第二条语句的执行速度比第一条快。当表中具有大量记录时,这种速度差异会更明显。
2.9为了速度放弃数据库结构的规范化
这是一种迫不得已的方法。放弃范式的规则不仅会增加数据库的冗余,还可能会带来修改、删除操作的错误。但是在数据规模很大时,多表查询只会带来致命的系统开销。为了避免进行多表查询操作,在实际应用中可以适当地增加数据冗余。
2.10为每个表都建立索引
索引可以提高查询速度,尽可能为数据库中的每一个表添加索引。
2.11分页显示用存储过程来实现
当数据库中表的数据量很大时,使用Recordset对象的分页属性,实现查询结果的分页就不再是一个很好的选择。因为这个属性先要把所有查询结果都提取出来,然后再根据获取的数据设置字段进行分页,在数据量很大时它的效率会很低。最好的解决办法是使用SQL语句查询出某一页的记录集。为了提高速度,还可以将这个SQL语句封装成数据库中的一个存储过程。
2.12数据库中尽量不要存储图片、文件等数据
为了减少数据库的负担,要把网站中的图片和文件存储在服务器的目录中。一般图片和文件的体积都很大,因此从数据库中查找和读取这些数据时,会大大增加应用程序的开销。
3网页优化
网页优化就是对页面信息和页面实现功能的方法进行优化。
3.1减少网页中的图片及其他多媒体信息
图片、动画、视频、音频可以使网页的内容丰富多彩,可以吸引用户的视线,但是它们也会大大增加系统的开销。如果网页打开速度受到网页上图片的影响,那么就要考虑对图片做适当的修改,如把每个图片的尺寸变小、分辨率降低等。对一些意义不是很大的图片最好删除。
3.2将有关下载的文件放在一个FTP服务器中
如果网站提供的下载内容很多,最好把可下载的文件放在FTP服务器中,和网站服务器相比它具有更高的文件传输效率。
3.3把动态页面替换成静态页面
如果在已经尝试过ASP的所有技术和方法后,还是解决不了访问速度的问题。就需要考虑把动态页面替换成静态的页面,用户访问静态页面,不需要服务器解释页面的内容,访问静态页面的速度必然比动态页面的快。