實(shí)例講解.NET應(yīng)用訪問數(shù)據(jù)庫(kù)的開銷問題
本文將從一個(gè)實(shí)例講述.NET應(yīng)用訪問數(shù)據(jù)庫(kù)的開銷問題。作者主要是從.NET應(yīng)用訪問數(shù)據(jù)庫(kù)的遍歷順序改進(jìn)講起。當(dāng)然,與之配套的也就是我們熟悉的SQL Server數(shù)據(jù)庫(kù)。
拿今天的一個(gè)例子說話吧,那就表中存放的是全國(guó)的地域信息,表結(jié)構(gòu)如下:
首先用代碼生成器和存儲(chǔ)過程生成器生成基本表的操作,推薦兩個(gè)工具:動(dòng)軟.Net代碼生成器- 全功能的三層架構(gòu).Net代碼生成器和codeplex上面的一個(gè)存儲(chǔ)過程生成工具Stored Procedure Generator (for SQL Server 2000/2005 ... 。
現(xiàn)在提供了一個(gè)方法,可以獲取***和二級(jí)地域的信息,最開始的做法是先獲取***的地域信息,然后循環(huán)***地域信息,獲取它的子節(jié)點(diǎn)。
- List<KB.DSN.Entity.District> topDistrictList = new List<KB.DSN.Entity.District>();
- KB.DSN.BusinessAccess.District dictrictBll = new KB.DSN.BusinessAccess.District();
- topDistrictList = dictrictBll.GetEntityList(string.Format("DisFatherCode='{0}' {1}", 0, Settings.District_Order_By));
- foreach (KB.DSN.Entity.District dis in topDistrictList)
- {
- dis.ChildrenDis = dictrictBll.GetEntityList(string.Format("DisFatherCode='{0}' {1}", dis.DisCode, Settings.District_Order_By));
- }
- return topDistrictList;
上面的做法,可以實(shí)現(xiàn)功能,***測(cè)試獲取一級(jí)和二級(jí)的地域信息,花費(fèi)時(shí)間5秒左右,不說能接受吧,起碼可以忍受。HttpWatch: An HTTP Viewer and HTTP Sniffer for IE and Firefox 這個(gè)工具可以查看瀏覽器獲取數(shù)據(jù)的時(shí)間。
后面又寫了一個(gè)方法,可以根據(jù)地域編號(hào)和想要獲取的層級(jí)數(shù)目,獲取指定地域下面的N層地域。和上面差不多,完成后一次是,一次獲取上海下面的二級(jí)花費(fèi)10秒,獲取三級(jí)50秒。這好像就不能忍受了吧。
然后進(jìn)行優(yōu)化,代碼如下,變成一次獲取二級(jí)的數(shù)據(jù),然后用C#代碼來(lái)生成層級(jí)關(guān)系。
- List<KB.DSN.Entity.District> districtList = new List<KB.DSN.Entity.District>();
- KB.DSN.BusinessAccess.District dictrictBll = new KB.DSN.BusinessAccess.District();
- districtList = dictrictBll.GetEntityList(string.Format(" {0} {1}", Settings.Get_Top_And_Second_District_Where,
- Settings.District_Order_By));
- var top = from c in districtList
- where c.DisFatherCode.Trim() == "0"
- select c;
- var second = from c in districtList
- where c.DisFatherCode.Trim() != "0"
- select c;
- foreach (KB.DSN.Entity.District dis in top)
- {
- var se = from c in second
- where c.DisFatherCode == dis.DisCode
- select c;
- dis.ChildrenDis = se as List<KB.DSN.Entity.District>;
- }
- return top as List<KB.DSN.Entity.District>;
作者后續(xù)
提到數(shù)據(jù)庫(kù)的訪問,尤其是遞歸層級(jí)調(diào)用問題,應(yīng)該減少往返數(shù)據(jù)庫(kù)的次數(shù),而是從數(shù)據(jù)庫(kù)將所需數(shù)據(jù)一次性獲取出來(lái),然后在C#代碼中處理成樹形層級(jí)關(guān)系,這樣會(huì)提升很大的效率。
其實(shí)遞歸這種東西,用在數(shù)值計(jì)算中還可以,如果是復(fù)雜處理就***不用了,很消耗CPU和內(nèi)存的,因?yàn)橐褂脳4娣藕芏鄡?nèi)容。只是代碼看起來(lái)好理解,量大、操作復(fù)雜還是轉(zhuǎn)成非遞歸的好。
如果層級(jí)不多,變化不大,可以考慮使用緩存,效率就會(huì)更高。具體緩存的應(yīng)用可以參看李天平的:系統(tǒng)緩存全解析 ,后面我可能也會(huì)寫一兩篇這方面的文章。
上一篇我們討論的數(shù)據(jù)是全國(guó)的行政地域信息,它有固定的格式。每個(gè)行政區(qū)劃的編碼長(zhǎng)度都是12位,總共分5級(jí)來(lái)管理,前兩位代表31個(gè)?。ㄖ陛犑校?,往后兩位代表一般的市(州),往后兩位代表市中的區(qū)(縣),往后三位是街道辦事處,***三位是居民委員會(huì)(社區(qū))。
系統(tǒng)中其實(shí)有很多類似的類型編碼都被 放在數(shù)據(jù)庫(kù)中,有的是一級(jí)的,有的是分層級(jí)關(guān)系的。就像上面的地域信息,全國(guó)的5級(jí)總共有8萬(wàn)左右條數(shù)據(jù)。***的辦法是一次將他們讀取到服務(wù)器的內(nèi)存中,形成樹形層級(jí),放在緩存中,如果有需要就直接獲取返回給客戶端,這樣可以較少很多的數(shù)據(jù)庫(kù)消耗。當(dāng)然,前提是這類信息的變動(dòng)很小,幾乎沒有變化。系統(tǒng)緩存全解析6:數(shù)據(jù)庫(kù)緩存依賴 中介紹了,可以使用數(shù)據(jù)庫(kù)依賴緩存,這樣就不怕數(shù)據(jù)庫(kù)內(nèi)容有變化了,如果有變化,會(huì)自動(dòng)更新緩存。緩存的正確使用,可以極大的提供效率
原文標(biāo)題:NET應(yīng)用訪問數(shù)據(jù)庫(kù)之?dāng)?shù)據(jù)庫(kù)的開銷問題
鏈接:http://www.cnblogs.com/virusswb/archive/2010/03/05/1679383.html
【編輯推薦】
- 淺談如何在SQL Server中生成腳本
- SQL Server使用索引實(shí)現(xiàn)數(shù)據(jù)訪問優(yōu)化
- SQL Server 05數(shù)據(jù)庫(kù)被置為“可疑”的解決方法
- 詳解SQL Server的版本區(qū)別及選擇
- SQL Server不存在或拒絕訪問故障的排除