好学IT学院:IT信息技术分享交流平台
标签:ASP  来源:CSDN  作者:本站整理  发布时间:2008-12-07  ★★★加入收藏〗〖手机版
摘要:纲要:ASP动态生成的内容以什么方式输出效率最高?最好用哪种方法提取数据库记录集?本文测试了近20个这类ASP开发中常见的问题,测试工具所显示的时间告诉我们:这些通常可以想当然的问题不仅值得关注,而且还有出乎意料的秘密隐藏在内。…

三、第一次测试

在第一次测试中,我们模拟Microsoft ASP ADO示例中可找到的典型情形提取一个记录集。在这个例子(ADO__01.asp)中,我们首先打开一个连接,然后创建记录集对象。当然,这里的脚本按照本文第一部分所总结的编码规则作了优化。

<% Option Explicit %>
<!-- #Include file="ADOVBS.INC" -->
<%
Dim objConn
Dim objRS

Response.Write( _
"<HTML><HEAD>" & _
"<TITLE>ADO Test</TITLE>" & _
"</HEAD><BODY>" _
)

Set objConn = Server.CreateObject("ADODB.Connection")
objConn.Open Application("Conn")

Set objRS = Server.CreateObject("ADODB.Recordset")
objRS.ActiveConnection = objConn
objRS.CursorType = adOpenForwardOnly
objRS.LockType = adLockReadOnly
objRS.Open Application("SQL")

If objRS.EOF Then
Response.Write("No Records Found")
Else
'write headings
Response.Write( _
"<TABLE BORDER=1>" & _
"<TR>" & _
"<TH>OrderID</TH>" & _
"<TH>CustomerID</TH>" & _
"<TH>EmployeeID</TH>" & _
"<TH>OrderDate</TH>" & _
"<TH>RequiredDate</TH>" & _
"<TH>ShippedDate</TH>" & _
"<TH>Freight</TH>" & _
"</TR>" _
)
'write data
Do While Not objRS.EOF
Response.Write( _
"<TR>" & _
"<TD>" & objRS("OrderID") & "</TD>" & _
"<TD>" & objRS("CustomerID") & "</TD>" & _
"<TD>" & objRS("EmployeeID") & "</TD>" & _
"<TD>" & objRS("OrderDate") & "</TD>" & _
"<TD>" & objRS("RequiredDate") & "</TD>" & _
"<TD>" & objRS("ShippedDate") & "</TD>" & _
"<TD>" & objRS("Freight") & "</TD>" & _
"</TR> " _
)
objRS.MoveNext
Loop
Response.Write("</TABLE>")
End If

objRS.Close
objConn.Close
Set objRS = Nothing
Set objConn = Nothing

Response.Write("</BODY></HTML>")
%>

下面是测试结果:

我们来看一下各栏数字的含义:
0返回0个记录的页面所需要的TTLB(毫秒)。在所有的测试中,该值被视为生成页面本身(包括创建对象)的时间开销,不包含循环访问记录集数据的时间。
25以毫秒计的提取和显示25个记录的TTLB
tot time/25"25"栏的TTLB除以25,它是每个记录的总计平均时间开销。
disp time/25"25"栏的TTLB减去"0"栏的TTLB,然后除以25。该值反映了在循环记录集时显示单个记录所需时间。
250提取和显示250个记录的TTLB。
tot time/250"250"栏的TTLB除以25,该值代表单个记录的总计平均时间开销。
disp time/250"250"栏的TTLB减去"0"栏的TTLB,再除以250。该值反映了在循环记录集时显示单个记录所需时间。

上面的测试结果将用来同下一个测试结果比较。

四、是否应该通过包含引用ADOVBS.inc?

Microsoft提供的ADOVBS.inc包含了270行代码,这些代码定义了大多数的ADO属性常量。我们这个示例只从ADOVBS.inc引用了2个常量。因此本次测试(ADO__02.asp)中我们删除了包含文件引用,设置属性时直接使用相应的数值。

objRS.CursorType = 0?' adOpenForwardOnly
objRS.LockType = 1' adLockReadOnly

可以看到页面开销下降了23%。该值并不影响单个记录的提取和显示时间,因为这里的变化不会影响循环内的记录集操作。有多种方法可以解决ADOVBS.inc的引用问题。我们建议将ADOVBS.inc文件作为参考,设置时通过注释加以说明。请记住,正如第一部分所指出的,适度地运用注释对代码的效率影响极小。另外一种方法是将那些需要用到的常量从ADOVBS.inc文件拷贝到页面内。

还有一个解决该问题的好方法,这就是通过链接ADO类型库使得所有的ADO常量直接可用。把下面的代码加入Global.asa文件,即可直接访问所有的ADO常量:

<!--METADATA TYPE="typelib"
FILE="C:Program FilesCommon FilesSYSTEMADOmsado15.dll"
NAME="ADODB Type Library" -->

或者:

<!--METADATA TYPE="typelib"
UUID="00000205-0000-0010-8000-00AA006D2EA4"
NAME="ADODB Type Library" -->

因此,我们的第一条规则为:

·避免包含ADOVBS.inc文件,通过其他方法访问和使用ADO常量。[NewCn_Pages]

五、使用记录集时是否应该创建单独的连接对象?

要正确地回答这个问题,我们必须分析两种不同条件下的测试:第一,页面只有一个数据库事务;第二,页面有多个数据库事务。

在前例中,我们创建了一个单独的Connection对象并将它赋给Recordset的ActiveConnection属性。然而,如ADO__03.asp所示,我们也可以直接把连接串赋给ActiveConnection属性,在脚本中初始化和配置Connection对象这一额外的步骤可以省去。

objRS.ActiveConnection = Application("Conn")

虽然Recordset对象仍旧要创建一个连接,但此时的创建是在高度优化的条件下进行的。因此,与上一次测试相比,页面开销又下降了23%,而且如预期的一样,单个记录的显示时间没有实质的变化。

因此,我们的第二个规则如下:

·如果只使用一个记录集,直接把连接串赋给ActiveConnection属性。

接下来我们检查页面用到多个记录集时,上述规则是否仍旧有效。为测试这种情形,我们引入一个FOR循环将前例重复10次。在这个测试中,我们将研究三种变化:

第一,如ADO__04.asp所示,在每一个循环中建立和拆除Connection对象:

Dim i
For i = 1 to 10

Set objConn = Server.CreateObject("ADODB.Connection")
objConn.Open Application("Conn")

Set objRS = Server.CreateObject("ADODB.Recordset")
objRS.ActiveConnection = objConn
objRS.CursorType = 0 'adOpenForwardOnly
objRS.LockType = 1 'adLockReadOnly
objRS.Open Application("SQL")
If objRS.EOF Then
Response.Write("No Records Found")
Else
'write headings
...
'write data
...
End If

objRS.Close
Set objRS = Nothing
objConn.Close
Set objConn = Nothing

Next

第二,如ADO__05.asp所示,在循环外面创建Connection对象,所有记录集共享该对象:

Set objConn = Server.CreateObject("ADODB.Connection")
objConn.Open Application("Conn")

Dim i
For i = 1 to 10
Set objRS = Server.CreateObject("ADODB.Recordset")
objRS.ActiveConnection = objConn
objRS.CursorType = 0 'adOpenForwardOnly
objRS.LockType = 1 'adLockReadOnly
objRS.Open Application("SQL")

If objRS.EOF Then
Response.Write("No Records Found")
Else
'write headings
...
'write data
...
End If

objRS.Close
Set objRS = Nothing

Next
objConn.Close
Set objConn = Nothing

第三,如ADO__06.asp所示,在每一个循环内把连接串赋给ActiveConnection属性:

Dim i
For i = 1 to 10

Set objRS = Server.CreateObject("ADODB.Recordset")
objRS.ActiveConnection = Application("Conn")
objRS.CursorType = 0 'adOpenForwardOnly
objRS.LockType = 1 'adLockReadOnly
objRS.Open Application("SQL")

If objRS.EOF Then
Response.Write("No Records Found")
Else
'write headings
...
'write data
...
End If

objRS.Close
Set objRS = Nothing
Next

就象我们可以猜想到的一样,在循环内创建和拆除连接对象是效率最差的方法。不过,令人惊异的是,在循环内直接把连接串赋给ActiveConnection属性只比共享单个连接对象稍微慢了一点。

尽管如此,第三规则应该为:

·同一页面内用到多个记录集时,创建单一的连接对象并通过ActiveConnection属性共享它。[NewCn_Pages]

六、哪种游标类型和记录锁定方式效率最高?

迄今为止的所有测试中我们只使用了“只能向前”的游标来访问记录集。ADO为记录集提供的游标还有三种类型:静态可滚动的游标,动态可滚动的游标,键集游标。每种游标都提供不同的功能,比如访问前一记录和后一记录、是否可以看到其他程序对数据的修改等。不过,具体讨论每一种游标类型的功用已经超出了本文的范围,下表是各种游标类型的一个比较性的分析。

和“只能向前”类型的游标相比,所有其它的游标类型都需要额外的开销,而且这些游标在循环内一般也要慢一些。因此,我们愿与您共享如下告诫:永远不要这样认为——“唔,有时候我会用到动态游标,那么我就一直使用这种游标吧。”

同样的看法也适用于记录锁定方式的选择。前面的测试只用到了只读的加锁方式,但还存在其他三种方式:保守式、开放式、开放式批处理方式。和游标类型一样,这些锁定方式为处理记录集数据提供了不同的功能和控制能力。

我们得出如下规则:

·使用适合于处理任务的最简单的游标类型和记录锁定方式。

七、最好用哪种方法提取记录集?

到目前为止我们一直通过创建Recordset对象提取记录集,但是ADO也提供了间接的记录集提取方法。下面的测试比较ADO__03.asp和直接从Connection对象创建记录集(CONN_01.asp)这两种方法:

Set objConn = Server.CreateObject("ADODB.Connection")
objConn.Open Application("Conn")

Set objRS = objConn.Execute(Application("SQL"))

可以看到页面开销略有增加,单个记录的显示时间没有变化。

下面我们再来看看从Command对象直接创建记录集对象(CMD__02.asp):

Set objCmd = Server.CreateObject("ADODB.Command")
objCmd.ActiveConnection = Application("Conn")
objCmd.CommandText = Application("SQL")

Set objRS = objCmd.Execute

同样,页面开销也略有增加,而单个记录的显示时间没有本质的变化。后面这两种方法在性能上的差异很小,但我们还有一个重要的问题需要考虑。

通过Recordset类创建记录集时,我们能够以最大的灵活性控制记录集的处理方式。既然后面两种方法未能有压倒性的性能表现,我们主要还是考虑默认返回的游标类型和记录锁定方式,对于某些场合来说默认值并不一定是最理想的。

因此,除非由于特殊的原因需要选择后面两种方法,否则我们建议考虑下面的规则:

·通过ADODB.Recordset类实例化记录集,以获得最好的性能和灵活性

利用FLASH技术实现眨眼睛的动画效果
  如何在FLASH中实现眨眼睛的动画效果,可以进行如下动画分析: 1.眉毛不动,单独占一层;2.眼睛睁开和闭合的时间间隔:本实例中…
  • 好学触屏公众号虎力全开、杨帆起航!
  • 四大名著全套小学生版注音版
  • 诗词中的科学全4册
  • 曹文轩系列儿童文学全套画本