提高ASP性能的最佳選擇(續(xù)一)
發(fā)表時(shí)間:2024-02-26 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]在本文的第一部分中,我回顧了有關(guān)ASP開發(fā)的一些基本問題,介紹了一些性能測(cè)試的結(jié)果,以理解我們放置在頁(yè)面中的代碼可能對(duì)運(yùn)行性能造成什么樣的影響。在這個(gè)系列的第二部分,我們將探討經(jīng)過論證的ASP最廣泛的用途,即通過ActiveX 數(shù)據(jù)對(duì)象(ADO)交互使用數(shù)據(jù)庫(kù)內(nèi)容。ADO是Microsoft通用并...
在本文的第一部分中,我回顧了有關(guān)ASP開發(fā)的一些基本問題,介紹了一些性能測(cè)試的結(jié)果,以理解我們放置在頁(yè)面中的代碼可能對(duì)運(yùn)行性能造成什么樣的影響。在這個(gè)系列的第二部分,我們將探討經(jīng)過論證的ASP最廣泛的用途,即通過ActiveX 數(shù)據(jù)對(duì)象(ADO)交互使用數(shù)據(jù)庫(kù)內(nèi)容。ADO是Microsoft通用并簡(jiǎn)單的數(shù)據(jù)庫(kù)界面。
ADO有很多的功能設(shè)置,因此準(zhǔn)備這篇文章時(shí)最大的挑戰(zhàn)便是限制測(cè)試問題的范圍?紤]到讀取大數(shù)據(jù)集會(huì)為web 服務(wù)器施加很大的負(fù)載,我決定將研究的內(nèi)容局限在為使用ADO記錄集尋找最優(yōu)化配置的方面。但是這個(gè)限制還是提出了一個(gè)挑戰(zhàn),因?yàn)锳DO為執(zhí)行同一個(gè)功能提供了多種方式。比如說,記錄集可以從Recordset 類中恢復(fù),也可以從Connection和Command 類中恢復(fù)。另外,一旦你有了一個(gè)記錄集,那么有很多個(gè)選擇會(huì)戲劇性地影響性能。因此,同第一部分一樣,我將盡可能地多涉及一些具體問題。
目的
我研究的目的是獲取足夠的信息以找到以下問題的答案:
* 是否應(yīng)該使用ADOVBS.inc包含文件?
* 當(dāng)使用一個(gè)記錄集時(shí),是否應(yīng)該創(chuàng)建一個(gè)單獨(dú)的Connection對(duì)象?
* 恢復(fù)一個(gè)記錄集最好的方法是什么?
* 指針和鎖的類型中,哪些是最有效的?
* 是否應(yīng)該使用斷開的記錄集?
* 設(shè)置記錄集(Recordset)屬性的最好方法是什么?
* 引用記錄集中域值的最有效方法是什么?
* 使用臨時(shí)字符串可以較好地代替緩沖器嗎?
測(cè)試是如何設(shè)立的?
為進(jìn)行這項(xiàng)研究中的測(cè)試,我們共組裝了21個(gè)ASP頁(yè)面(包含在本文下載內(nèi)容中)。每個(gè)頁(yè)面都被配置成用3個(gè)不同的查詢返回記錄集運(yùn)行,這些記錄集中分別有0、25、250條記錄。這可以幫助我們將裝載記錄集的問題和在記錄集中循環(huán)上的性能問題隔離開。
為滿足這些變化的條件,數(shù)據(jù)庫(kù)連接字符串和測(cè)試SQL字符串都作為應(yīng)用程序變量存儲(chǔ)在Global.asa中。因?yàn)槲覀兊臏y(cè)試數(shù)據(jù)庫(kù)是在Microsoft SQL Server 7.0上運(yùn)行的,因此我們的連接字符串指定OLEDB作為連接供應(yīng)者、Northwind 樣本數(shù)據(jù)庫(kù)(包含在SQL服務(wù)器中)作為當(dāng)前數(shù)據(jù)庫(kù)。SQL SELECT語(yǔ)句要求Northwind Orders 表格中的7個(gè)特定域。
< SCRIPT LANGUAGE=VBScript RUNAT=Server >
Sub Application_OnStart
Application("Conn") = "Provider=SQLOLEDB; " & _
"Server=MyServer; " & _
"uid=sa; " & _
"pwd=;" & _
"DATABASE=northwind"
Application("SQL") = "SELECT TOP 0 OrderID, " & _
" CustomerID, " & _
" EmployeeID, " & _
" OrderDate, " & _
" RequiredDate, " & _
" ShippedDate, " & _
" Freight " & _
"FROM [Orders] "
End Sub
< /SCRIPT >
'alternate sql ?25 records
Application("SQL") = "SELECT TOP 25 OrderID, " & _
" CustomerID, " & _
" EmployeeID, " & _
" OrderDate, " & _
" RequiredDate, " & _
" ShippedDate, " & _
" Freight " & _
"FROM [Orders] "
'alternate sql ?250 records
Application("SQL") = "SELECT TOP 250 OrderID, " & _
" CustomerID, " & _
" EmployeeID, " & _
" OrderDate, " & _
" RequiredDate, " & _
" ShippedDate, " & _
" Freight " & _
"FROM [Orders] "
我們的測(cè)試服務(wù)器是一個(gè)雙450 MHz Pentium ,512MB的RAM,在其上運(yùn)行著NT Server 4.0 SP5, MDAC 2.1 (數(shù)據(jù)訪問組件)以及Microsoft Scripting Engine的5.0版本。SQL服務(wù)器在一個(gè)同樣規(guī)格的單獨(dú)機(jī)器上運(yùn)行。同第一篇文章一樣,我使用Microsoft的Web應(yīng)用程序重點(diǎn)工具記錄從最初的頁(yè)面請(qǐng)求到傳輸最后一個(gè)字節(jié)(TTLB )的時(shí)間,精確到服務(wù)器上的毫秒級(jí)。這個(gè)測(cè)試腳本運(yùn)行20小時(shí),調(diào)用每個(gè)頁(yè)面1300次以上。顯示的時(shí)間是session的平均TTLB。要記住的是,同第一篇文章一樣,我們只是試圖涉及性能方面的問題,而非伸縮性和容量的問題。
還請(qǐng)注意,我們?cè)诜⻊?wù)器上開啟了緩沖器。另外,我把所有的文件名都定為同樣長(zhǎng)度,因此文件名中就會(huì)有一個(gè)或多個(gè)下劃線來襯墊。
開始
在第一個(gè)測(cè)試中,我們使用典型Microsoft ASP ADO 樣本文件中的典型場(chǎng)景來恢復(fù)一個(gè)簡(jiǎn)單的記錄集。在這個(gè)例子( ADO__01.asp )中,我們首先創(chuàng)建一個(gè)Connection對(duì)象,然后創(chuàng)建一個(gè)Recordset對(duì)象。當(dāng)然,我在腳本中進(jìn)行了一些修改,以反映在本系列的第一部分中涉及到的一些好的做法。
< % 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 >")
% >
結(jié)果是這樣的:
現(xiàn)在先來看看每一欄中的數(shù)字代表什么:
0 代表運(yùn)行返回0個(gè)記錄的查詢時(shí)的TTLB,單位毫秒。在我們所有測(cè)試中,這個(gè)數(shù)字用來標(biāo)志頁(yè)面的負(fù)載或裝載頁(yè)面創(chuàng)建對(duì)象但不在數(shù)據(jù)中循環(huán)所用的時(shí)間。
25 裝載并顯示25條記錄的TTLB(毫秒)。
tot time/25 TTLB除以25條記錄(毫秒)。代表每條記錄的總平均時(shí)間。
disp time/25 以毫秒計(jì)的TTLB減去“0”那欄的TTLB,并除以25條記錄。代表在記錄集中循環(huán)顯示每條記錄的時(shí)間。
250 裝載并顯示250條記錄的TTLB(毫秒)。
tot time/250 TTLB除以250條記錄(毫秒)。代表每條記錄的總平均時(shí)間。
disp time/250 以毫秒計(jì)的TTLB減去“0”那欄的TTLB,并除以250條記錄。代表在記錄集中循環(huán)顯示每條記錄的時(shí)間。
我們將用下面測(cè)試的結(jié)果與這些值相比較。
是否應(yīng)該使用ADOVBS.inc 包含文件?
這個(gè)問題我想快點(diǎn)解決。Microsoft 提供的ADOVBS.inc 文件包含270行代碼,代表可以應(yīng)用于ADO屬性的大部分常量。我們的例子中只引用了這個(gè)文件中的2個(gè)常量。因此對(duì)于這個(gè)測(cè)試( ADO__02.asp ),我取消了包含文件的引用,并用屬性列舉中的實(shí)際數(shù)字代替了常量。
objRS.CursorType = 0 ' adOpenForwardOnly
objRS.LockType = 1 ' adLockReadOnly
我們可以看到裝載時(shí)間減少了23%。這與每條記錄的顯示時(shí)間有定義上的不同,因?yàn)檫@種改變對(duì)于在記錄集中循環(huán)不應(yīng)該有影響。這個(gè)問題有幾種解決辦法。我建議使用ADOVBS.inc 文件作為參考,必要時(shí)使用注釋來注明數(shù)字。要記住,就如同在第一部分所闡明的一樣,注釋是不需要懼怕的,因?yàn)橹灰褂眠m度,它們不會(huì)給性能帶來大的影響。另一種方法是只從文件中將你所需要的常量復(fù)制到頁(yè)面中。
解決這個(gè)問題有一個(gè)很酷的方法,通過將ADO類庫(kù)連接到你的應(yīng)用程序,使所有的ADO常量都可用。將以下代碼增加到你的Global.asa 文件,你就可以直接使用所有的常量。
< !--METADATA TYPE="typelib"
FILE="C:\Program Files\Common Files\SYSTEM\ADO\msado15.dll"
NAME="ADODB Type Library" -- >
或
< !--METADATA TYPE="typelib"
UUID="00000205-0000-0010-8000-00AA006D2EA4"
NAME="ADODB Type Library" -- >
所以,這里是我們的第一個(gè)規(guī)則:
* 避免包含ADOVBS.inc文件,用其它方法來使用常量。