上學(xué)時(shí),因我年齡最小,個(gè)頭也最小,上課時(shí),就像大猩猩堆里的猴一般。如今,這猴偶爾也把最近的一些情況寫在這里。
2. Ado.Net 2.1 應(yīng)用Ado.net的一些思考原則 1. 根據(jù)數(shù)據(jù)使用的方式來設(shè)計(jì)數(shù)據(jù)訪問層 2. 緩存數(shù)據(jù),避免不必要的操作 3. 使用服務(wù)帳戶進(jìn)行連接 4. 必要時(shí)申請,盡早釋放 5. 關(guān)閉可關(guān)閉的資源 6. 減少往返 7. 僅返回需要的數(shù)據(jù) 8. 選擇適當(dāng)?shù)氖聞?wù)類型 9. 使用存儲(chǔ)過程 2.2 Connection 數(shù)據(jù)庫連接是一種共享資源,并且打開和關(guān)閉的開銷較大。Ado.net默認(rèn)啟用了連接池機(jī)制,關(guān)閉連接不會(huì)真的關(guān)閉物理連接,而只是把連接放回到連接池中。因?yàn)槌刂泄蚕淼倪B接資源始終是有限的,如果在使用連接后不盡快關(guān)閉連接,那么就有可能導(dǎo)致申請連接的線程被阻塞住,影響整個(gè)系統(tǒng)的性能表現(xiàn)。 2.2.1 在方法中打開和關(guān)閉連接 這個(gè)原則有幾層含義: 1. 主要目的是為了做到必要時(shí)申請和盡早釋放 2. 不要在類的構(gòu)造函數(shù)中打開連接、在析構(gòu)函數(shù)中釋放連接。因?yàn)檫@將依賴于垃圾回收,而垃圾回收只受內(nèi)存影響,回收時(shí)機(jī)不定 3. 不要在方法之間傳遞連接,這往往導(dǎo)致連接保持打開的時(shí)間過長
這里強(qiáng)調(diào)一下在方法之間傳遞連接的危害:曾經(jīng)在壓力測試中遇到過一個(gè)測試案例,當(dāng)增大用戶數(shù)的時(shí)候,這個(gè)案例要比別的案例早很久就用掉連接池中的所有連接。經(jīng)分析,就是因?yàn)锳方法把一個(gè)打開的連接傳遞到了B方法,而B方法又調(diào)用了一個(gè)自行打開和關(guān)閉連接的C方法。在A方法的整個(gè)運(yùn)行期間,它至少需要占用兩條連接才能夠成功工作,并且其中的一條連接占用時(shí)間還特別長,所以造成連接池資源緊張,影響了整個(gè)系統(tǒng)的可伸縮性! 2.2.2 顯式關(guān)閉連接 Connection對象本身在垃圾回收時(shí)可以被關(guān)閉,而依賴?yán)厥帐呛懿缓玫牟呗浴M扑]使用using語句顯式關(guān)閉連接,如下例:
2.2.3 確保連接池啟用 Ado.net是為每個(gè)不同的連接串建立連接池,因此應(yīng)該確保連接串不會(huì)出現(xiàn)與具體用戶相關(guān)的信息。另外,要注意連接串是大小寫敏感的。 2.2.4 不要緩存連接 例如,把連接緩存到Session或Application中。在啟用連接池的情況下,這種做法沒有任何意義。 2.3 Command 2.3.1 使用ExecuteScalar和ExecuteNonQuery 如果想返回像Count(*)、Sum(Price)或Avg(Quantity)那樣的單值,可以使用ExecuteScalar方法。ExecuteScalar返回第一行第一列的值,將結(jié)果集作為標(biāo)量值返回。因?yàn)閱为?dú)一步就能完成,所以ExecuteScalar不僅簡化了代碼,還提高了性能。 使用不返回行的SQL語句時(shí),例如修改數(shù)據(jù)(INSERT、UPDATE或DELETE)或僅返回輸出參數(shù)或返回值,請使用ExecuteNonQuery。這避免了用于創(chuàng)建空DataReader的任何不必要處理。 2.3.2 使用Prepare 當(dāng)需要重復(fù)執(zhí)行同一SQL語句多次,可考慮使用Prepare方法提升效率。需要注意的是,如果只是執(zhí)行一次或兩次,則完全沒有必要。例如:
2.3.3 使用綁定變量 ★ SQL語句需要先被編譯成執(zhí)行計(jì)劃,然后再執(zhí)行。如果使用綁定變量的方式,那么這個(gè)執(zhí)行計(jì)劃就可以被后續(xù)執(zhí)行的SQL語句所復(fù)用。而如果直接把參數(shù)合并到了SQL語句中,由于參數(shù)值千變?nèi)f化,執(zhí)行計(jì)劃就難以被復(fù)用了。例如上面Prepare一節(jié)給出的示例,如果把參數(shù)值直接寫到insert語句中,那么上面的四次調(diào)用將需要編譯四次執(zhí)行計(jì)劃。 為避免這種情況造成性能損失,要求一律使用綁定變量方式。 2.4 DataReader DataReader最適合于訪問只讀的單向數(shù)據(jù)集。與DataSet不同,數(shù)據(jù)集并不全部在內(nèi)存中,而是隨不斷發(fā)出的read請求,一旦發(fā)現(xiàn)數(shù)據(jù)緩沖區(qū)中的數(shù)據(jù)均被讀取,則從數(shù)據(jù)源傳輸一個(gè)數(shù)據(jù)緩沖區(qū)大小的數(shù)據(jù)塊過來。另外,DataReader保持連接,DataSet則與連接斷開。 2.4.1 顯式關(guān)閉DataReader 與連接類似,也需要顯式關(guān)閉DataReader。另外,如果與DataReader關(guān)聯(lián)的Connection僅為DataReader服務(wù)的話,可考慮使用Command對象的ExecuteReader(CommandBehavior.CloseConnection)方式。這可以保證當(dāng)DataReader關(guān)閉時(shí),同時(shí)自動(dòng)關(guān)閉Connection。 2.4.2 用索引號(hào)訪問代替名稱索引號(hào)訪問屬性 從Row中訪問某列屬性,使用索引號(hào)的方式比使用名稱方式有細(xì)微提高。如果會(huì)被頻繁調(diào)用,例如在循環(huán)中,那么可考慮此類優(yōu)化。示例如下:
2.4.3 使用類型化方法訪問屬性 從Row中訪問某列屬性,用GetString、GetInt32這種顯式指明類型的方法,其效率較通用的GetValue方法有細(xì)微提高,因?yàn)椴恍枰鲱愋娃D(zhuǎn)換。 2.4.4 使用多數(shù)據(jù)集 部分場景可以考慮一次返回多數(shù)據(jù)集來降低網(wǎng)絡(luò)交互次數(shù),提升效率。示例如下:
2.5 DataSet 2.5.1 利用索引加快查找行的效率 如果需要反復(fù)查找行,建議增加索引。有兩種方式: 1. 設(shè)置DataTable的PrimaryKey 適用于按PrimaryKey查找行的情況。注意此時(shí)應(yīng)調(diào)用DataTable.Rows.Find方法,一般慣用的Select方法不能利用索引。 2. 使用DataView 適用于按Non-PrimaryKey查找行的情況。可為DataTable創(chuàng)建一個(gè)DataView,并通過SortOrder參數(shù)指示建立索引。此后使用Find或FindRows查找行。
Copyright @ 思勤無邪 Powered by: .Text and ASP.NET Theme by: .NET Monster