楊薇 王斌 楊永國(guó)
1 .91550部隊(duì)指控中心 遼寧 116023
2 .91550部隊(duì)220所 遼寧 116023
本文介紹了基于B/S模式的綜合電子設(shè)備管理系統(tǒng)開發(fā)過(guò)程中使用的各種系統(tǒng)優(yōu)化技術(shù),這些優(yōu)化技術(shù)的運(yùn)用降低了網(wǎng)絡(luò)延時(shí)、增強(qiáng)了服務(wù)器的并發(fā)處理能力,減少了重復(fù)的系統(tǒng)開銷,提高了數(shù)據(jù)庫(kù)的訪問(wèn)性能,使得系統(tǒng)的穩(wěn)定性和高效性得以保證,對(duì)其它基于B/S模式的信息系統(tǒng)的優(yōu)化具有一定的借鑒意義。
在實(shí)際系統(tǒng)開發(fā)過(guò)程中,是選用 DataReader還是DataSet,取決于以下幾點(diǎn):
(1) 內(nèi)存消耗
DataReader和DataSet之間的主要區(qū)別是前者的內(nèi)存開銷要比后者更小。DataReader是一個(gè)一次只能訪問(wèn)單行記錄信息的對(duì)象,不管結(jié)果集的大小,用DataReader來(lái)回移動(dòng)該結(jié)果集時(shí),一次只有單行記錄加載到內(nèi)存中;另一方面,DataSet是專門為內(nèi)存緩存大量數(shù)據(jù)而設(shè)計(jì)的,DataSet要比DataReader耗費(fèi)更多內(nèi)存;因此在訪問(wèn)數(shù)據(jù)時(shí),如果內(nèi)存不是最需要考慮的問(wèn)題時(shí),可以使用 DataSet,否則應(yīng)選用DataReader。
(2) 遍歷方向
在一個(gè)數(shù)據(jù)庫(kù)應(yīng)用程序中傳遞數(shù)據(jù)時(shí),必須考慮數(shù)據(jù)的遍歷方向,可以根據(jù)數(shù)據(jù)遍歷的方向要求來(lái)改善程序的性能。
如果以HTML形式通過(guò)ASP.NET頁(yè)面顯示結(jié)果集中的所有記錄,可以使用DataReader,它專門用于在一個(gè)方向上快速讀出和顯示數(shù)據(jù);當(dāng)不需要在緩沖區(qū)中進(jìn)行數(shù)據(jù)修改等操作,也不需要索引隨機(jī)訪問(wèn)數(shù)據(jù)記錄時(shí),DataReader是一個(gè)更好的選擇,它能提高程序的性能。
(3) 多個(gè)結(jié)果集
DataReader和DataSet都支持多個(gè)結(jié)果集的概念,但實(shí)現(xiàn)方式不同,DataReader通過(guò)NextResult方法來(lái)支持訪問(wèn)多個(gè)結(jié)果集,而DataSet將多個(gè)結(jié)果集加載到不同的DataTable對(duì)象中;使用DataSet時(shí),可以訪問(wèn)其中不同的DataTable對(duì)象來(lái)訪問(wèn)返回的不同結(jié)果集,而用DataReader訪問(wèn)多個(gè)結(jié)果集時(shí),只能進(jìn)行向前、只讀的操作。這意味著如果某個(gè)結(jié)果集先前已經(jīng)被訪問(wèn)過(guò),那么除非重置DataReader再?gòu)念^顯示,否則不能再訪問(wèn)該數(shù)據(jù)集。
綜合以上的分析,在實(shí)際開發(fā)過(guò)程中,對(duì)于需要讀取大量數(shù)據(jù)并且對(duì)返回?cái)?shù)據(jù)不做大量處理時(shí)候,我們使用了DataReader;對(duì)于需要返回并處理大量數(shù)據(jù)的時(shí)候,我們使用了DataSet。而且,我們還發(fā)現(xiàn),盡量不要對(duì)DataSet進(jìn)行二次加工,特別是不要對(duì) DataSet進(jìn)行大量刪除,因?yàn)檫@會(huì)很慢,不如復(fù)制部分?jǐn)?shù)據(jù)。
存儲(chǔ)過(guò)程是存儲(chǔ)在服務(wù)器上的一組預(yù)編譯的SQL語(yǔ)句,類似于DOS系統(tǒng)中的批處理文件。存儲(chǔ)過(guò)程具有對(duì)數(shù)據(jù)庫(kù)立即訪問(wèn)的功能,信息處理極為迅速。使用存儲(chǔ)過(guò)程可以避免對(duì)命令的多次編譯,在執(zhí)行一次后其執(zhí)行規(guī)劃就駐留在高速緩存中,客戶執(zhí)行存儲(chǔ)過(guò)程時(shí),只需調(diào)用服務(wù)器上的存儲(chǔ)過(guò)程(有時(shí)傳遞存儲(chǔ)過(guò)程所需的參數(shù)值)而不用發(fā)送整個(gè) SQL語(yǔ)句。另外,存儲(chǔ)過(guò)程在服務(wù)器端運(yùn)行,獨(dú)立于 ASP.NET程序,便于修改,最重要的是它可以減少數(shù)據(jù)庫(kù)操作語(yǔ)句在網(wǎng)絡(luò)中的傳輸。
在EIMS系統(tǒng)的開發(fā)過(guò)程中,在有規(guī)律地多次執(zhí)行一條或多條相關(guān)的SQL語(yǔ)句和多客戶有規(guī)律地執(zhí)行包含SQL語(yǔ)句的批命令情況下,我們使用了存儲(chǔ)過(guò)程來(lái)進(jìn)行數(shù)據(jù)處理,當(dāng)應(yīng)用發(fā)生改變時(shí),只需更改數(shù)據(jù)庫(kù)服務(wù)器上的相關(guān)存儲(chǔ)過(guò)程,使得系統(tǒng)調(diào)試、升級(jí)、維護(hù)都變得方便,提高了系統(tǒng)的靈活性。
系統(tǒng)在訪問(wèn)數(shù)據(jù)庫(kù)的時(shí)候需要?jiǎng)?chuàng)建連接、打開連接和關(guān)閉連接幾個(gè)操作。這些過(guò)程需要多次與數(shù)據(jù)庫(kù)交換信息以通過(guò)身份驗(yàn)證,比較耗費(fèi)服務(wù)器資源。ASP.NET中提供了連接池(Connection Pool)改善打開和關(guān)閉數(shù)據(jù)庫(kù)對(duì)系統(tǒng)性能的影響。連接池(Connection Pool)是連接對(duì)象的集合體,是指擁有一定數(shù)量的連接對(duì)象的“緩沖存儲(chǔ)池”。連接池內(nèi)部提供一種管理機(jī)制,能控制連接池內(nèi)部連接對(duì)象的個(gè)數(shù)、使用次數(shù)和時(shí)間,對(duì)應(yīng)用程序提供獲取和釋放連接的接口。
建立連接池能顯著地提高應(yīng)用程序的性能和可伸縮性。連接池是根據(jù)每個(gè)惟一的連接字符串創(chuàng)建的,當(dāng)創(chuàng)建一個(gè)池后,將按最小池大小的要求創(chuàng)建多個(gè)連接對(duì)象并將其添加到該池中。在請(qǐng)求連接時(shí),將根據(jù)需要添加到池中,直至達(dá)到連接池上限。當(dāng)達(dá)到上限且沒(méi)有可用的連接,則該請(qǐng)求將會(huì)被排入等待隊(duì)列。當(dāng)連接被釋放回池中時(shí),連接池管理程序通過(guò)重新分配連接來(lái)滿足這些請(qǐng)求。
在EIMS系統(tǒng)的開發(fā)過(guò)程中,我們使用了以下方法發(fā)揮連接池的特性來(lái)提高系統(tǒng)性能。包括:在建立數(shù)據(jù)庫(kù)連接后只有在真正需要操作時(shí)才打開連接,數(shù)據(jù)操作完成后立即顯示地關(guān)閉數(shù)據(jù)庫(kù)連接,以將其返回至池中,避免連接泄露;在關(guān)閉連接時(shí)刪除臨時(shí)對(duì)象;用不同的連接字符串以生成多個(gè)不同的連接池;在Web.Config中存儲(chǔ)單個(gè)連接字符串;使用ConfigurationSettings.AppSettings,以在運(yùn)行時(shí)采用編程形式對(duì)其進(jìn)行訪問(wèn)。
ASP.NET中ADO連接消耗的資源相當(dāng)大,SQL語(yǔ)句運(yùn)行的時(shí)間越長(zhǎng),占用系統(tǒng)資源的時(shí)間也越長(zhǎng)。因此,在開發(fā)過(guò)程中,我們盡量使用優(yōu)化過(guò)的SQL語(yǔ)句以減少執(zhí)行時(shí)間,使用到的優(yōu)化措施包括:盡量不在查詢語(yǔ)句中包含子查詢語(yǔ)句;在有Index的情況下,盡量保證查詢使用了正確的Index;查詢時(shí)使用匹配的類型,如在select * from a where id=9,如果這里ID是字符類型,同時(shí)有index,這條查詢則使用不到Index,會(huì)做全表掃描,速度會(huì)很慢。正確的應(yīng)該是 where id=”9”,加上引號(hào)表明類型是字符;使用—log-slow-querieslong-query-time=2查看查詢比較慢的語(yǔ)句,然后使用explain分析查詢,做出優(yōu)化。
大量的網(wǎng)站頁(yè)面是采用動(dòng)態(tài)的方式,根據(jù)用戶提交的不同請(qǐng)求創(chuàng)建生成頁(yè)面。動(dòng)態(tài)頁(yè)面有助于根據(jù)用戶要求來(lái)提供定制的動(dòng)態(tài)內(nèi)容,動(dòng)態(tài)頁(yè)面也利于獲取在數(shù)據(jù)庫(kù)中每時(shí)每刻更新的資料,其缺點(diǎn)是為每個(gè)用戶請(qǐng)求生成同一頁(yè)面增加了系統(tǒng)開銷。
ASP.NET提供了緩存技術(shù)有助于我們最大程度地解決這個(gè)問(wèn)題。它能緩存輸出的頁(yè)面,保存在存儲(chǔ)器當(dāng)中,緩存用戶請(qǐng)求的內(nèi)容。緩存的特點(diǎn)可以根據(jù)不同方式來(lái)定制。ASP.NET 提供了一些簡(jiǎn)單的機(jī)制,它們會(huì)在不需要為每個(gè)頁(yè)請(qǐng)求動(dòng)態(tài)計(jì)算頁(yè)輸出或數(shù)據(jù)時(shí)緩存這些頁(yè)輸出或數(shù)據(jù)。另外,通過(guò)設(shè)計(jì)要進(jìn)行緩存的頁(yè)和數(shù)據(jù)請(qǐng)求(特別是在站點(diǎn)中預(yù)期將有較大通訊量的區(qū)域),可以優(yōu)化這些頁(yè)的性能。適當(dāng)?shù)厥褂镁彺婵梢愿玫奶岣哒军c(diǎn)的性能,有時(shí)這種提高是超數(shù)量級(jí)的。
在開發(fā)過(guò)程中,我們使用 ASP.NET 緩存機(jī)制時(shí)注意了以下兩點(diǎn)。首先,盡量減少緩存的項(xiàng),緩存每個(gè)項(xiàng)均有開銷,特別是在內(nèi)存使用方面;不緩存容易重新計(jì)算和很少使用的項(xiàng),需要緩存的項(xiàng)包括:整個(gè)應(yīng)用程序都要使用的設(shè)置或?qū)ο?,?jīng)常被訪問(wèn)、并且變化不大的數(shù)據(jù),如電子設(shè)備的基本信息等;其次,給緩存的項(xiàng)分配的有效期不要太短。很快到期的項(xiàng)會(huì)導(dǎo)致緩存中不必要的周轉(zhuǎn),并且經(jīng)常導(dǎo)致更多的代碼清除和垃圾回收工作。
ASP.NET是一種事件驅(qū)動(dòng)的和基于控件的編程模型,因此提供了大量的服務(wù)器控件可供使用。服務(wù)器控件就是在服務(wù)器端解析的控件,這些控件經(jīng)過(guò)處理后會(huì)生成客戶端呈現(xiàn)代碼發(fā)送到客戶端。服務(wù)器控件帶來(lái)的方便和功能是html控件所不能比擬的,但是每一個(gè)服務(wù)器控件都需要在服務(wù)器端創(chuàng)建相應(yīng)的對(duì)象,是以犧牲服務(wù)器端的資源為代價(jià)的,過(guò)多的使用服務(wù)器控件會(huì)極大影響程序性能。因此,在使用服務(wù)器控件的時(shí)候,我們采用了以下策略來(lái)減少對(duì)程序性能的影響:
(1) 減少不必要的服務(wù)器控件
有時(shí)使用html標(biāo)記或數(shù)據(jù)綁定即能夠?qū)崿F(xiàn)所需功能,比如<asp:Label>控件,有時(shí)只用它來(lái)顯示靜態(tài)信息,此時(shí)就可以用簡(jiǎn)單的標(biāo)記來(lái)實(shí)現(xiàn)。在html控件達(dá)不到所要實(shí)現(xiàn)的功能,而且其它腳本語(yǔ)言如 javascript、vbscript也不能實(shí)現(xiàn)的情況下,才考慮選擇服務(wù)器控件。
(2) 禁用不必要的狀態(tài)視圖
服務(wù)器控件的 ViewState屬性能夠自動(dòng)的在頁(yè)面往返過(guò)程中維護(hù)服務(wù)器控件的狀態(tài),減少開發(fā)者的工作量,但是需要占用大量的服務(wù)器內(nèi)存資源。因此,在不需要服務(wù)器控件狀態(tài)視圖的情況下,如在頁(yè)面設(shè)計(jì)中經(jīng)常使用的<asp:Lable>和<asp:Button>控件,應(yīng)將其EnableViewState屬性設(shè)置為false以減少不必要的資源占用。
(3) 合理使用DataGrid控件
DataGrid控件帶有最強(qiáng)大的數(shù)據(jù)顯示功能,還內(nèi)置了對(duì)數(shù)據(jù)的修改、刪除、添加、分頁(yè)等很多功能。DataGrid控件的分頁(yè)功能,數(shù)據(jù)的存儲(chǔ)方式等雖然使用起來(lái)方便快捷,但是系統(tǒng)開銷比較大。因此,在只需簡(jiǎn)單顯示數(shù)據(jù)列表時(shí),選擇Repeater或DataList控件同樣可以達(dá)到目的,而且減輕了性能上的開銷。
基于 B/S模式的系統(tǒng)性能調(diào)整與優(yōu)化是一個(gè)較大的話題,涉及的方面很多,如網(wǎng)絡(luò)傳輸、并發(fā)處理、內(nèi)容緩存、服務(wù)器緩存、數(shù)據(jù)庫(kù)優(yōu)化等。本文根據(jù)EIMS系統(tǒng)的開發(fā)實(shí)踐,介紹了數(shù)據(jù)庫(kù)訪問(wèn)優(yōu)化,緩存管理,頁(yè)面優(yōu)化等優(yōu)化策略的應(yīng)用。由于系統(tǒng)本身的特點(diǎn),使用到的優(yōu)化策略有限,本文只對(duì)常規(guī)的優(yōu)化技術(shù)進(jìn)行了應(yīng)用剖析。隨著并發(fā)訪問(wèn)量的增大,反向代理緩存、Web負(fù)載均衡、數(shù)據(jù)庫(kù)擴(kuò)展、分布式計(jì)算等技術(shù)也將對(duì)優(yōu)化系統(tǒng)性能起到重要的作用。
[1] Soumyasch,File:DotNEt.svg.2009.http://en.wikipedia.org/wiki/Fi le:DotNet.svg.
[2] 熊慧芳,陳莉.基于 ADO.NET的數(shù)據(jù)庫(kù)訪問(wèn)技術(shù)研究[J].科技廣場(chǎng).2007.
[3] 李宗英.SQL存儲(chǔ)過(guò)程在.NET數(shù)據(jù)庫(kù)中的運(yùn)用[J].信息科技.2008.
[4] 金燦,陳瑞君等.NET框架中三種數(shù)據(jù)庫(kù)訪問(wèn)技術(shù)及效率比較[J].計(jì)算機(jī)應(yīng)用研究.2003.
[5] 劉志波.NET中統(tǒng)一的存儲(chǔ)過(guò)程調(diào)用方法[J].計(jì)算機(jī)應(yīng)用.2003.
[6] 謝招犇,李衛(wèi)華.數(shù)據(jù)庫(kù)連接池模型的分析與優(yōu)化[J].現(xiàn)代計(jì)算機(jī).2006.