提高ADO效能的優秀經驗(轉)

來源:互聯網
上載者:User
ado|效能 一、概述

  “效能”這一術語有著幾種不同的、差異微妙的含義。當人們談到某個東西效能多少好時,他們想要表達的意思可能就是在一定的時間之內它完成了多少工作。例如,一個效能好的發動機運行起來更穩定,產生的動力更強大。對於開發小組,你同樣也可能應用這個判斷標準:一個效能好的開發小組工作時比較安靜,而且能夠生產出大量高品質的代碼。對我來說,效能至少意味著兩件事情——My Code運行起來有多好,我的開發小組和我本人工作效率怎麼樣。無論哪一方面,本文介紹的技巧都將起到一定的協助作用:協助你更快地編寫代碼,協助你編寫更快的代碼——安靜地完成這一切,減少這樣那樣的錯誤。本文介紹的技巧主要面向ADO,特別是如何通過ADO訪問SQL Server。但與此同時,我還將涉及一些適用範圍更廣的COM技巧,它們適用於你所編寫的所有Visual Basic代碼。

  為了瞭解從哪些SQL Server資料存取碼編寫技術、哪些體系、哪些開發習慣可以得到最好的效能,我已經花了不少時間。一些情況下,對於應用的整體效能來說,單一的技術意義很小,除非我們通過迴圈將效能的改善程度成倍放大。例如,在一個客戶機/伺服器應用中,當我們不是通過指定ODBC資料來源(DSN)的方式串連資料庫時,大約能夠節省一到二秒的時間。對於應用整體的適用性或效能來說,這部分節省的時間所產生的影響很小。但是,如果我們在一個中介層組件上應用這種技術,這個組件每分鐘(或每小時,每天)都要建立和關閉資料庫連接數百(甚至數千)次,那麼,這種技術將顯著地影響系統的效能表現。因此,對於我在這裡討論的每一種技術,請務必考慮這個倍數因子——即,在一定的時間周期內,你的系統將執行同一段代碼多少次。

  當你開始尋求改進效能的方案時,請考慮一下你的應用(組件,或者是ASP代碼)大部份的等待和處理時間花在什麼地方。如果你發現應用程式把大量的時間花在等待Open或Execute方法執行完成,那麼,你應該認真地檢查一下伺服器端的查詢策略。包括ADO在內,所有的資料提供者等待查詢結果的時間都相同。例如,如果你有一個查詢,SQL Server需要20秒才能完成它,不論用來執行該查詢的是什麼介面,沒有一種介面能夠比其他介面以更快的速度返回結果。雖然有些介面開啟串連的速度比較快,有些介面處理結果集的速度比較快,但沒有一種介面能夠影響資料庫引擎編譯和執行查詢的速度。因此,如果你的查詢具有太高的“挑戰性”——例如你沒有對索引進行最佳化,你沒有使用預存程序,伺服器負載過重,或者你要求返回的記錄數量太多——那麼,世界上沒有一種ADO技術能夠協助你提高效能。除非你解決了這些基本的查詢問題,否則沒有一種效能調整技術能夠顯著地改善整體效能。SQL Server的Query Analyzer是一個分析查詢效能的優秀工具。它能夠用圖形的方式顯示查詢的執行過程,並對改進效能的方法提出建議。

  如果你能夠確信查詢具有較高的效率,那麼,你可以使用本文介紹的技術進一步調整ADO代碼的效能。這裡介紹的技巧將從各個方面協助你簡化和改進ADO編程,包括:建立和維護串連,構造和提交執行速度更快的查詢,提高處理查詢結果的效率,等等。

二、建立串連

  在一個客戶機/伺服器應用中,我們可以用好幾種方法把建立和初始化資料庫連接所需要的時間隱藏起來,使得應用程式既能夠開啟串連,又不需要使用者等待應用程式啟動。首先,我們可以嘗試非同步串連。使用非同步串連時,ADO啟動串連操作之後,不等待串連完成就把控制權返回給應用程式——這樣,應用程式就能夠接著執行大部份初始化操作,以更快的速度完成form_load事件處理。如果關閉並重建立立串連的時間小於串連池釋放串連的時間,那麼這個串連實際上是即時的。但在許多情況下(特別是使用者數量不多時),讓串連保持開啟狀態更具有現實意義。在中介層組件或ASP頁面內部,如果資料庫查詢多次重複出現,我建議你讓Connection對象保持開啟狀態。

  另外一個改進串連效能的辦法是,避免使用帶有DSN的ODBC。在Microsoft,ODBC已經轉入了Quick Fix Engineering(QFE,快速修理工程)狀態,它意味著:除非發現重大BUG,該公司將不再在ODBC或它的驅動程式上花時間。另外,考慮效能和部署問題時,ODBC DSN也是一個必須關注的問題。DSN必須安裝到客戶系統上,要求進行註冊表尋找,與OLE DB串連相比,它建立串連所需要的時間更長——特別是當你用直接編碼的方式指定ConnectionString時,這一點尤其突出。從實際效果來看,避免使用DSN降低的系統開銷很有限:如果完全取消串連建立過程,對於每個串連,你也許能夠剩下二到五秒時間(假設資料庫連接池中已經沒有串連)。然而,如果你的應用程式需要頻繁地建立串連,節省的時間累計起來就很可觀了。

  建立資料庫連接的時候,你要選擇一個資料提供者。Microsoft建議我們使用OLE DB提供者替代預設的ODBC提供者。對比最新的OLE DB本地提供者和功能類似但較早的ODBC提供者,我感到前者令人不愉快的意外之事較少。但無論是哪種情況,你都應該在決定使用某個新的提供者之前對應用進行完整地測試——代碼的效能、支援的功能、行為方式都有可能發生變化。

  在中介層和ASP中,在保持串連開啟的情況下,我們不能(從實踐來看)建立出可伸縮的組件——至少在多次調用之間是這樣的。一般地,當IIS引用和釋放組件、ASP頁面的執行個體時,組件和ASP頁面被頻繁地裝入、丟棄。由於基於ADO的代碼每次執行時都必須建立、使用、釋放資料庫連接,最小化串連複雜程度的策略對效能的提高程度達到了可明顯測量的程度。在這些情形下,對於我們串連資料庫的速度來說,串連/會話池有著重要的意義。如果你為Command對象的ConnectionString屬性指定合適的值(即,每次使用同樣的伺服器、初始目錄、登入ID和其他參數),那麼,串連已經開啟且處於可用狀態的機會很大。如果串連池中能夠找到匹配的串連,串連(或重新串連)的時間將接近0(通常小於250 ms)。

  然而,如果ADO(或VB)代碼不釋放Connection對象,或者,我們在不同的執行個體之間改換了ConnectionString,OLE DB必須每次建立一個新的串連。如果出現了這種情況,我們將很快耗盡串連池內可用串連的數量。要確保串連被釋放,我們必須在關閉串連之後把Connection對象設定為Nothing。另外,不要在Recordset Open方法中使用ConnectionString,而是以獨立的方式開啟Connection對象;這樣,當我們要關閉Connection對象以及要把它設定成Nothing的時候,引用它就很方便了。

三、構造和提交查詢

  在構造查詢的時候,要搞清楚為什麼必須這麼做、為什麼不能那麼做是一個很複雜的問題。然而,一些基本的指導方針能夠讓構造高效查詢的過程更加流暢、輕鬆。一般地,你不應該讓查詢浪費伺服器時間。下面幾個技巧能夠協助你構造出更好、更高效的查詢。

  不要強制SQL Server每次執行查詢的時候重新編譯和構造查詢執行計畫。避免這種重複操作的一種簡單方法是使用帶有參數的預存程序。注意盡量不要使用ADO Command對象的Prepare屬性——有時它不能正確工作。如果使用預存程序,你還可以通過消除不必要的“受影響行數”傳回值進一步提高ADO效能——只需在預存程序中加入SET NOCOUNT ON就可以了。

  盡量減少與伺服器的通訊次數。如果你有幾個相關的操作要執行,請把它們合并為一個預存程序,或者是一個可以在伺服器上作為指令碼執行的複合查詢。避免使用方法(比如Refresh)和不適當的Parameters集合引用,它們會強制ADO增加額外的伺服器通訊過程。

  在客戶機/伺服器應用中,只構造Command對象一次,而不是每次使用Command對象的時候重新構造。你可以重新設定Command的參數值,然後在需要時執行它。

  當查詢返回的不是一個記錄集時,確保使用了adExecuteNoRecords選項,告訴ADO越過所有那些用來接收和構造記錄集(Recordset格式)的代碼。你可以把adExecuteNoRecords選項傳遞給Execute方法,或把它作為Command的選項。

  執行返回簡單記錄集的預存程序時,不要使用Command對象。所有的預存程序(以及Command對象)可以作為Connection對象的COM方法出現。讓預存程序作為Connection對象的方法出現有著顯著的效能優勢,同時它也簡化了代碼。儘管這種技術對於那些有Return Status值或Output參數的預存程序沒有什麼協助,但對於巨集指令查詢(INSERT、DELETE等)以及那些返回一個或多個記錄的查詢來說,這種技術很有用。把預存程序作為Connection的方法之後,你可以用方法參數的形式傳入預存程序的輸入參數;如果調用預存程序返回了一個記錄集,你可以通過方法調用中最後一個參數引用該Recordset。例如,下面的ADO語句執行一個名為“Fred”的預存程序,Fred預存程序有兩個輸入參數,返回一個Recordset:

MyConnection.Fred  "InputArg1", 2, myRecordset



  編寫代碼的時候,不要寄希望於VB的自動完成功能會把預存程序或Command對象名字視為合法的Connection對象的方法。在正式運行之前,COM不會解析這類名字。

  除非絕對必要,否則不要返回記錄集。當正在執行的查詢返回記錄時,ADO就會構造一個Recordset對象。構造Recordset對象的開銷很大,因此你應該盡量避免使用Recordset對象。注意有時候執行查詢雖然返回結果,但不是返回記錄。例如,你可以通過Return Status參數返回整數值。另外,你可以返回Output參數來替代需要構造Recordset對象的記錄集,SQL Server允許返回的Output參數多達1000個。

  只要有可能,請用巨集指令查詢(INSERT,UPDATE,DELETE和執行這些操作的預存程序)替代可更新的Recordset遊標。此時,你應該使用Execute方法和它的adExecuteNoRecords選項,確保ADO能夠知道查詢不需要構造Recordset對象。

  除非必要,否則不要請求伺服器進行排序。大多數情況下,對於一個適度大小的Recordset對象,當它被發送到用戶端之後,排序速度將更快。另外,如果讓ADO客戶程式排序Recordset中的記錄,則客戶應用程式能夠按照使用者選擇的次序排序,從而提高了靈活性。

  在編寫查詢之前瞭解索引的結構。建立合適的索引,調整查詢的文法以利用這些索引,你將能夠提高記錄提取的速度。Query Analyzer能夠協助你決定是否有必要添加更多的索引。

  不要一次性返回太多的記錄。很多時候,容量太大的記錄集會嚴重



相關文章

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。