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