PRiya DhawanMicrosoft Developer Network
January 2002
原文鏈接:https://msdn.microsoft.com/en-us/library/ms978388.aspx
概要:在典型的應(yīng)用環(huán)境中,比較不同數(shù)據(jù)訪問技術(shù)的表現(xiàn)性能。適用于Microsoft .NET Framework Beta2 和 Microsoft SQL Server 2000.(23頁打印頁)
簡介
數(shù)據(jù)訪問方式的架構(gòu)選擇會對程序的性能、擴展性、可維護性和易用性帶來影響。這篇文章的重點在于論述這些選擇產(chǎn)生的不同性能表現(xiàn)。數(shù)據(jù)訪問技術(shù)包括:Microsoft ADO.NET Command,DataReader,DataSet和xmlReader,這里使用Microsoft SQL ServerTM 2000數(shù)據(jù)庫比較這些不同技術(shù)在一些典型的應(yīng)用環(huán)境下的區(qū)別。在這些比較當中,會在一定的用戶負載范圍內(nèi)對Customer,Order和OrderDetail 數(shù)據(jù)執(zhí)行一系列的命令操作。
展示這些不同數(shù)據(jù)訪問技術(shù)的代碼示例同樣可以使用在討論ADO.NET的數(shù)據(jù)訪問技術(shù)的相關(guān)文章當中。這些例子包括了使用ADO.NET訪問單個值,單行,多行和層次數(shù)據(jù)。
測試場景
任何數(shù)據(jù)操作的性能表現(xiàn)取決于以下因素:
數(shù)據(jù)訪問中的對象構(gòu)造和對象填充會帶來很大的系統(tǒng)開銷。比如,使用ADO.NET的DataSet進行實例和填充操作就比使用DataReader或XMLReader進行同樣操作要占用更多的系統(tǒng)開銷。
數(shù)據(jù)訪問技術(shù)對數(shù)據(jù)庫造成的負載情況是不一樣的。比如,應(yīng)用程序讀取數(shù)據(jù)時,DataSet和DataReader使用的連接方式是不一樣的。使用存儲過程的數(shù)據(jù)訪問技術(shù)就比使用動態(tài)SQL表達式的方式要少一些數(shù)據(jù)庫的工作負荷。關(guān)系型數(shù)據(jù)與XML之間的轉(zhuǎn)化對服務(wù)器資源的使用也與此類似。
對數(shù)據(jù)庫的數(shù)據(jù)往返訪問的數(shù)量也是一個因素,特別是在鎖和事務(wù)跨越多個數(shù)據(jù)來回。
通過網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)量也是一個關(guān)鍵因素,呈現(xiàn)為xml格式的數(shù)據(jù)比其它格式的數(shù)據(jù)要大很多。
我們使用一些在業(yè)務(wù)應(yīng)用當中常用的操作,比如獲取一個客戶列,查詢一個客戶的相關(guān)訂單或者插入一個訂單,來比較ADO.NET的不同的數(shù)據(jù)訪問技術(shù)。為了使測試更加可靠,數(shù)據(jù)庫加載了超過100,000行的客戶賬號,一百萬行訂單(每個客戶10個訂單)和超過五百萬行的訂單細節(jié)(每個訂單有5個細節(jié))。這些數(shù)據(jù)存在一個SQL Server 2000數(shù)據(jù)庫當中,通過SQL Server .NET data provider連接到SQL Server中。在這里比較的一些方法使用了SQL Server 2000的XML特性。
GetOrderStatusGetOrderStatus方法接受一個OrderId,然后返回一個表示這個訂單狀態(tài)的整型。
GetCustomerGetCustomer方法接受一個CustomerId參數(shù),然后返回關(guān)于該客戶信息的一行記錄。
GetCustomersGetCustomers方法接受一個CustomerId和一個指明你要讀取的行數(shù)的參數(shù)。在所有CustomerID大于傳給網(wǎng)頁服務(wù)方法的CustomerID的行中,將讀取最上面的n行數(shù)據(jù),并返回。
我們在一大堆具有不同頁數(shù)的客戶記錄中執(zhí)行帶分頁的測試。這些客戶記錄的頁數(shù)分別為:100,500和1000。
GetOrdersGetOrders方法從數(shù)據(jù)庫獲取一系列層次訂單和它們對應(yīng)的細節(jié)。這個方法接受一個OrderId和一個指明要讀取多少訂單數(shù)的參數(shù)。在所有OrderId大于傳入的OrderId的記錄當中,最上面的n行記錄將被讀取到。
我們在一大堆具有不同頁數(shù)的客戶記錄中執(zhí)行帶分頁的測試。這些客戶記錄的頁數(shù)分別為:10個訂單(50個細節(jié)),50個訂單(250個細節(jié))和100個訂單(500個細節(jié))。
InsertCustomerInsertCustomer方法接受一個customer數(shù)據(jù),并向數(shù)據(jù)庫中插入一個customer行,然后將CustomerId作為一個整型返回。
InsertCustomersInsertCustomers方法接受一系列customer類集合,然后向數(shù)據(jù)庫中插入多行對應(yīng)的customer記錄。
InsertOrderInsertOrder方法接受的數(shù)據(jù),包含了一個帶多個detail數(shù)據(jù)的order記錄,并把對應(yīng)的Order和OrderDetails信息插入數(shù)據(jù)庫當中。測試方法通過插入一個order表頭和不同的details來進行。
測試工具
基于我們的測試目的,我們使用application Center Test(ACT),它適合用于對Web服務(wù)器進行壓力測試,并分析Web程序的性能和擴展性問題。Web程序就包括ASP頁面和它們使用的組件。要了解更多關(guān)于創(chuàng)建和運行測試的方法,請參考ACT documentation。使用ACT來測試Web服務(wù)器中的不同數(shù)據(jù)訪問技術(shù)是很適合的,因為它提供了很多有用的功能來完成測試。首先,它可以通過打開多個對服務(wù)器的連接和快速發(fā)送HTTP請求來模擬一大組客戶并發(fā)操作。其次,它也允許我們建立真實的測試環(huán)境,在其中我們可以使用有一系列隨機參數(shù)調(diào)用同樣的一個方法。這是一個很重要的功能,因為用戶不應(yīng)該反復(fù)地利用同樣的參數(shù)調(diào)用同樣的方法。另一個更重要的功能就是,Application Center Test會記錄測試結(jié)果,這些測試結(jié)果可以提供關(guān)于Web程序性能表現(xiàn)的最重要的信息。
雖然直接測試數(shù)據(jù)訪問技術(shù),而不是像我們這樣通過Web服務(wù)器來測試,會讓我們得到更好的吞吐量和響應(yīng)時間,但是在一個無狀態(tài)的環(huán)境下更接近真實的程序應(yīng)用環(huán)境。并且,因為我們基本上是比較這些數(shù)據(jù)訪問技術(shù)的相對性能,在無狀態(tài)環(huán)境(也就是在Web服務(wù)器背后)中,測試的系統(tǒng)開銷在所有情況下都是一樣的。
我們之前討論的所有數(shù)據(jù)訪問技術(shù)都通過.NET Framework程序集進行實施。使用ACT對程序集產(chǎn)生客戶負載,我們實現(xiàn)wrapper.aspx頁面,所有的客戶請求全部都送到這個界面,然后調(diào)用程序集。這些程序集中的方法實施了使用ADO.NET技術(shù)的數(shù)據(jù)操作。他們是一些簡單的子過程,并不會向.aspx 頁面返回數(shù)據(jù)。當從數(shù)據(jù)庫獲得數(shù)據(jù)行后,這些方法在記錄行中進行迭代,然后把列值賦給本地變量。通過在讀取從ADO.NET對象中得到的數(shù)據(jù)時添加延遲,我們模擬使用這些數(shù)據(jù)進行一些處理操作時的開銷。
測試腳本使用Microsoft VBScript進行編寫。根據(jù)在test script中執(zhí)行的具體方法,我們隨機化對不同的Customer或Order的請求。比如:
Dim URL Dim UB, LB ' Set the upperbound for Orders list UB = 1000000 ' Set the lowerbound for Orders list LB = 1 ' Set the URL URL = "http://myServer/DataAccessPerf/DataReader.aspx" ' Use the Randomize funtion to initialize the Rnd function Randomize Test.SendRequest(URL & "?OrderId=" & int((UB – LB + 1)*Rnd + LB))機器配置
下面的表格對進行測試的測試臺配置進行了一個概要總結(jié):
表1.客戶機配置
| # of Clients | Machine/CPU | # of CPUs | Memory | Disk | Software |
|---|---|---|---|---|---|
| 1 | Dell Precision WorkStation530 MT1694 MHz | 1 | 512 MB | 16.9 GB |
|
表2. Web服務(wù)器配置
| # of Servers | Machine/CPU | # of CPUs | Memory | Disk | Software |
|---|---|---|---|---|---|
| 1 | Compaq Proliant 400 MHz | 4 | 640 MB | 50 GB |
|
表3. 數(shù)據(jù)庫服務(wù)器配置
| # of Servers | Machine/CPU | # of CPUs | Memory | Disk | Software |
|---|---|---|---|---|---|
| 1 | American Megatrends Atlantis800 MHz | 2 | 1 GB | 28 GB |
|
性能測試結(jié)果
GetOrderStatus這里我們比較使用不同的數(shù)據(jù)訪問技術(shù)從數(shù)據(jù)庫獲取單個值的表現(xiàn)。

圖1. GetOrderStatus: 吞吐量和延遲
注解
如圖1所示,ExecuteScalar,Output Parameter和DataReader方法獲取單個值得性能表現(xiàn)在所有用戶負載范圍內(nèi)都很接近。
但ExecuteScalar方法比其它方法需要更少的代碼,因此,從代碼維護性的角度來說,是最好的選擇。
XMLReader方法與其它方法相比,會產(chǎn)生更低的尖峰吞吐量,并且包含了FOR XML查詢的存儲過程會比其它方法使用的存儲過程花費更多的時間。
GetCustomer這里我們比較從數(shù)據(jù)庫獲取單行記錄時不同數(shù)據(jù)訪問技術(shù)的表現(xiàn)差異。

圖2. GetCustomer: 吞吐量和延時
注解:
如圖2所示,Output參數(shù)和DataReader的方法在不同用戶負載范圍內(nèi)表現(xiàn)一致,并且產(chǎn)生比較好的網(wǎng)絡(luò)吞吐量,均比另外兩種方法好。XmlReader方法在吞吐量和響應(yīng)時間方面表現(xiàn)稍微比DataSet好一些。
在XmlReader方法中,使用FOR XML的SQL查詢比其它方法要花更長的執(zhí)行時間。
在這中情況下,DataSet對象的創(chuàng)建引起的系統(tǒng)開銷是導(dǎo)致了比較低的吞吐量的主要原因。
GetCustomers在這個部分,我們比較讀取多行記錄時(各數(shù)據(jù)訪問技術(shù)的)性能表現(xiàn)。我們分別進行返回結(jié)果集有100行,500行,1000行記錄的測試,以觀察數(shù)據(jù)返回量對性能的影響。

圖 3. GetCustomers (Customers=100): 吞吐量和延時
注解:
正如你所預(yù)料的,從數(shù)據(jù)庫讀取更多地行記錄會降低每秒的請求數(shù),因為需要處理更多的行記錄,并發(fā)送這些行記錄。
圖3顯示了DataReader方法的吞吐量幾乎比另外兩種方法大兩倍。DataSet和XmlReader方法的性能表現(xiàn)幾乎一樣,不過,在吞吐量方面,XmlReader比DataSet方法稍微好一點點。

圖4. GetCustomers (Customers=500): 吞吐量和延時
<新聞熱點
疑難解答
圖片精選