六、哪種游標類型和記錄鎖定方式效率最高?
迄今為止的所有測試中我們只使用了“只能向前”的游標來訪問記錄集。ADO為記錄集提供的游標還有三種類型:靜態可滾動的游標,動態可滾動的游標,鍵集游標。每種游標都提供不同的功能,比如訪問前一記錄和后一記錄、是否可以看到其他程序對數據的修改等。不過,具體討論每一種游標類型的功用已經超出了本文的范圍,下表是各種游標類型的一個比較性的分析。
和“只能向前”類型的游標相比,所有其它的游標類型都需要額外的開銷,而且這些游標在循環內一般也要慢一些。因此,我們愿與您共享如下告誡:永遠不要這樣認為——“唔,有時候我會用到動態游標,那么我就一直使用這種游標吧!
同樣的看法也適用于記錄鎖定方式的選擇。前面的測試只用到了只讀的加鎖方式,但還存在其他三種方式:保守式、開放式、開放式批處理方式。和游標類型一樣,這些鎖定方式為處理記錄集數據提供了不同的功能和控制能力。
我們得出如下規則:
l使用適合于處理任務的最簡單的游標類型和記錄鎖定方式。
七、最好用哪種方法提取記錄集?
到目前為止我們一直通過創建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類創建記錄集時,我們能夠以最大的靈活性控制記錄集的處理方式。既然后面兩種方法未能有壓倒性的性能表現,我們主要還是考慮默認返回的游標類型和記錄鎖定方式,對于某些場合來說默認值并不一定是最理想的。
因此,除非由于特殊的原因需要選擇后面兩種方法,否則我們建議考慮下面的規則:
l通過ADODB.Recordset類實例化記錄集,以獲得最好的性能和靈活性。
八、是否應該使用本地記錄集?
ADO允許使用本地(客戶端)記錄集,此時查詢將提取記錄集內的所有數據,查詢完成后連接可以立即關閉,以后使用本地的游標訪問數據,這為釋放連接帶來了方便。使用本地記錄集對于訪問那些要求數據離線使用的遠程數據服務非常重要,那么,對于普通的應用它是否同樣有所幫助?
下面我們加入CursorLocation屬性,并在打開記錄集之后關閉了連接(CLIENT1.asp):
Set objRS = Server.CreateObject("ADODB.Recordset")
objRS.CursorLocation = 2' adUseClient
objRS.ActiveConnection = Application("Conn")
objRS.LockType = 1?' adLockReadOnly
objRS.Open Application("SQL")
objRS.ActiveConnection = Nothing
理論上,這種方法由于以下兩個原因會對效率有所好處:第一,它避免了在記錄之間移動時重復地通過連接請求數據;第二,由于能夠方便地釋放連接,它減輕了資源需求。然而,從上表看起來使用本地記錄集對提高效率顯然沒有什么幫助。這或許是因為使用本地記錄集時,不管程序設置的是什么,游標總是變成靜態類型。
第6個規則如下:
l除非確實要求記錄集本地化,否則應避免使用。
十、用哪種方法引用記錄集字段值效率最高?
10.1 測試
至此為止我們一直通過名字引用記錄集中的字段值。由于這種方法要求每次都必須尋找相應的字段,它的效率并不高。為證明這一點,下面這個測試中我們通過字段在集合中的索引引用它的值(ADO__08.asp):
'write data
Do While Not objRS.EOF
Response.Write( _
"< TR >" & _
"< TD >" & objRS(0) & "< /TD >" & _
"< TD >" & objRS(1) & "< /TD >" & _
"< TD >" & objRS(2) & "< /TD >" & _
"< TD >" & objRS(3) & "< /TD >" & _
"< TD >" & objRS(4) & "< /TD >" & _
"< TD >" & objRS(5) & "< /TD >" & _
"< TD >" & objRS(6) & "< /TD >" & _
"< /TR > " _
)
objRS.MoveNext
Loop
和預期的一樣,頁面開銷也有小小的變化(這或許是因為代碼略有減少)。然而,這種方法在顯示時間上的改善是相當明顯的。
在下一個測試中,我們把所有的字段分別綁定到變量(ADO__09.asp):
If objRS.EOF Then
Response.Write("No Records Found")
Else
'write headings
...
Dim fld0
Dim fld1
Dim fld2
Dim fld3
Dim fld4
Dim fld5
Dim fld6
Set fld0 = objRS(0)
Set fld1 = objRS(1)
Set fld2 = objRS(2)
Set fld3 = objRS(3)
Set fld4 = objRS(4)
Set fld5 = objRS(5)
Set fld6 = objRS(6)
'write data
Do While Not objRS.EOF
Response.Write( _
"< TR >" & _
"< TD >" & fld0 & "< /TD >" & _
"< TD >" & fld1 & "< /TD >" & _
"< TD >" & fld2 & "< /TD >" & _
"< TD >" & fld3 & "< /TD >" & _
"< TD >" & fld4 & "< /TD >" & _
"< TD >" & fld5 & "< /TD >" & _
"< TD >" & fld6 & "< /TD >" & _
"< /TR >" _
)
objRS.MoveNext
Loop
Set fld0 = Nothing
Set fld1 = Nothing
Set fld2 = Nothing
Set fld3 = Nothing
Set fld4 = Nothing
Set fld5 = Nothing
Set fld6 = Nothing
Response.Write("< /TABLE >")
End If
這是目前為止最好的記錄。請注意單個記錄的顯示時間已經降低到0.45毫秒以下。
上述腳本都要求對結果記錄集的構造有所了解。例如,我們在列標題中直接使用了字段名字,單獨地引用各個字段值。下面這個測試中,不僅字段數據通過遍歷字段集合得到,而且字段標題也用同樣的方式得到,這是一種更為動態的方案(ADO__10.asp)。
If objRS.EOF Then
Response.Write("No Records Found")
Else
'write headings Response.Write("< TABLE BORDER=1 >< TR >")
For Each objFld in objRS.Fields
Response.Write("< TH >" & objFld.name & "< /TH >")
Next
Response.Write("< /TR >")
'write data
Do While Not objRS.EOF
Response.Write("< TR >")
For Each objFld in objRS.Fields
? Response.Write("< TD >" & objFld.value & "< /TD >")
Next
Response.Write("< /TR >")
objRS.MoveNext
Loop
Response.Write("< /TABLE >")
End If
可以看到,代碼性能有所下降,但它仍舊要比ADO__07.asp要快。
下一個測試示例是前面兩個方法的折衷。我們將繼續保持動態特征,同時通過在動態分配的數組中保存字段引用提高性能:
If objRS.EOF Then
Response.Write("No Records Found")
Else
Dim fldCount
fldCount = objRS.Fields.Count
Dim fld()
ReDim fld(fldCount)
Dim i
For i = 0 to fldCount-1
Set fld(i) = objRS(i)
Next
'write headings
Response.Write("< TABLE BORDER=1 >< TR >") For i = 0 to fldCount-1
Response.Write("< TH >" & fld(i).name & "< /TH >")
Next
Response.Write("< /TR >")
'write data
Do While Not objRS.EOF
Response.Write("< TR >")
For i = 0 to fldCount-1
Response.Write("< TD >" & fld(i) & "< /TD >")
Next
Response.Write("< /TR >")
objRS.MoveNext
Loop
For i = 0 to fldCount-1
Set fld(i) = Nothing
Next
Response.Write("< /TABLE >")
End If
雖然還不能超過以前最好的成績,但它比開頭的幾個示例要快,同時它具有動態地處理任何記錄集這一優點。
文章來源于領測軟件測試網 http://www.kjueaiud.com/