top
Loading...
什么才是提高ASP性能的最佳選擇(續二)
當使用一個記錄集時,是否應該創建一個單獨的Connection對象?

要想正確回答這個問題,需要在兩個不同情況下檢驗測試結果:第一是每頁執行一個數據庫處理的情況,第二是每頁執行多個數據庫處理的情況。

在前面的例子中,我們已經創建了一個單獨的Connection對象,并將它傳遞到記錄集的ActiveConnection 屬性。但是也有可能僅僅把連接字符串傳遞到這個屬性中,從而可以避免一個額外的步驟,即在腳本( ADO__03.asp )中例示和配置一個單獨的組件:

objRS.ActiveConnection = Application("Conn")

盡管我們仍然在記錄集中創建了一個連接,但它是在非常優化的情況下創建的,所以剛一開始我們就看到啟動時間比以前的測試減少了23%,同預料中一樣,同每個記錄的顯示時間幾乎沒有什么差別。

因此,我們的第二個規則是:

* 當使用一個單個記錄集時,將連接字符串傳遞到ActiveConnection屬性中。

下面要確定當在一個頁面上創建多個記錄集時,這個邏輯是否依然成立。為測試這個情況,我引入了FOR 循環,將前面的例子重復10次。在這個測試中,我們還將研究3種選擇:

第一,我們在每個循環中創建并銷毀Connection 對象( ADO__04.asp ):

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

第二,在循環外創建一個單獨的Connection 對象,并與每個記錄集共享它( ADO__05.asp ):

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

第三,在每個循環中將連接字符串傳遞到ActiveConnection 屬性( ADO__06.asp ):

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

你可能已經猜到了,在每個循環中創建并銷毀Connection 對象是一個低效率的方法。但是令人吃驚的是,僅僅在每個循環中傳遞連接字符串比共享單一連接對象的效率只低一點點。

盡管如此,我們的第3條規則是:

* 在一個頁面上使用多個記錄集時,創建一個Connection 對象,在ActiveConnection 屬性中重復使用它。

指針和鎖的類型中,哪些是最有效的?

到目前為止,我們所有測試都只用了只向前(Forward Only )的指針在記錄集中循環。但是,ADO還為記錄集提供了3種類型的指針:Static, Dynamic 和 Keyset。每一種都提供了額外的功能,比如向前和向后移動以及當別人建立數據時可以看到修改情況的功能。不過,討論這些指針類型的內涵不是本文討論的范圍。我把這些留給你自己。下面是各種類型的比較分析。

與它們的同類Forward Only 相比,這些額外的指針都明顯地造成了更大的負載( ADO__03.asp )。另外這些指針在循環期間也更慢。我想與你一起分享的一條忠告是要避免這種想法:“我不時地需要一下Dynamic 指針,所以干脆總是用它算了。”

從本質上說,同樣的問題也適用于鎖的類型。前面的測試中只使用了Read Only(只讀)類型的鎖。但是,還有三種類型的鎖:Lock Pessimistic、 Lock Optimistic和Lock Batch Optimistic。同指針的選擇一樣,這些鎖也為處理記錄集中的數據提供了額外的功能和控制。同樣,我將學習每種鎖設置的適當用途的內容留給你自己。

所以引導我們考慮規則4的邏輯很簡單:使用最適合你的任務的最簡單的指針和鎖的類型。

獲取一個記錄集最好的方式是什么?

到目前為止,我們只是通過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 對象中直接創建一個Recordset 對象( CMD__01.asp ):

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

我們再次看到負載有一個輕微的增加,每個記錄的顯示時間有一個名義上的區別。雖然最后這兩種方法對性能的影響很小,卻有一個大問題需要考慮。

通過Recordset 類創建一個記錄集對于控制如何處理記錄集提供了最大的靈活性。雖然其它方法也沒有提出一個壓倒性的性能問題,但是你會被默認狀態下返回何種指針類型和鎖類型而困惑,這些對于你的特定需求來說不一定是最優的。

所以,除非因為某種特殊原因你需要其它方法的話,請遵循第5條規則:通過ADODB.Recordset 類例示記錄集以獲得最好的性能和最大的靈活性。

是否應該斷開記錄集?

ADO為斷開一個記錄集提供了一種選擇,記錄集要在一個向前查詢中恢復所有數據、關閉連接、使用一個本地(或客戶)指針在數據集中移動。這還提供了一個早期釋放連接的機會。這種情況對于處理遠程數據服務是必要的,因為這種情況下數據必須從數據庫斷開。但是對于普通的用途,這樣做有好處嗎?

下面我們增加了CursorLocation 屬性,打開記錄集后關閉連接( CLIENT1.asp ):

Set objRS = Server.CreateObject("ADODB.Recordset")
objRS.CursorLocation = 3 ' adUseClient
objRS.ActiveConnection = Application("Conn")
objRS.LockType = 1 ' adLockReadOnly
objRS.Open Application("SQL")
objRS.ActiveConnection = Nothing

從理論上說,這個技術應該導致性能更快。原因有兩個:首先,在記錄集中移動時,避免了通過連接的重復請求;其次通過較早地取消連接減輕了資源需求。但是,在使用客戶端指針時,效率低得很明顯。可能是由于當使用客戶指針位置時,不管你的設置是什么,CursorType 都被修改成Static。

規則6是這樣的:除非是一個斷開的環境中所要求的,避免使用斷開的記錄集。

什么是設置記錄集屬性的最好方法?

前面所有的測試都是通過單獨的屬性設置來直接設置記錄集的屬性的。但是Recordset.Open 函數可以為我們所需要的全部屬性接收額外的參數。雖然對于每個屬性來說,單獨的代碼行易于閱讀和維護,它們還是要分別執行一個單獨函數調用,必須通過COM界面來集合( ADO__07.asp ):

Set objRS = Server.CreateObject("ADODB.Recordset")
objRS.Open Application("SQL"), Application("Conn"), 0, 1
' adForwardOnly, adLockReadOnly

這些方法在負載上帶來得差別小得驚人,于是我們得到規則7:不要對單獨設置記錄集屬性感到擔心。

北斗有巢氏 有巢氏北斗