劉冬 周彬
摘 要:本文從SQL SERVER 數(shù)據(jù)庫的范式優(yōu)化、查詢優(yōu)化、索引優(yōu)化等方面出發(fā),對數(shù)據(jù)庫的性能優(yōu)化方法進(jìn)行探討,總結(jié)了數(shù)據(jù)庫優(yōu)化應(yīng)遵循的方法,力圖提高SQL語句的執(zhí)行效率。
數(shù)據(jù)庫技術(shù)的應(yīng)用已由傳統(tǒng)數(shù)據(jù)處理發(fā)展至圖像處理、商業(yè)決策管理等更多的新興領(lǐng)域,而這些新興領(lǐng)域?qū)π畔⑾到y(tǒng)的高效、安全、穩(wěn)定的性能要求更高。如何有效組織及處理數(shù)據(jù)庫中的海量數(shù)據(jù), 保證系統(tǒng)吞吐量, 成為數(shù)據(jù)庫優(yōu)化的首要任務(wù)。本文針對數(shù)據(jù)庫優(yōu)化技術(shù)探索合適的方法,從范式優(yōu)化、查詢優(yōu)化、索引優(yōu)化等多個方面進(jìn)行探討,希望可以通過這些優(yōu)化使信息系統(tǒng)更適用于人們的需求。
1 合理使用范式
關(guān)系模式規(guī)范化的目的是為了消除存儲異常、減少數(shù)據(jù)冗余,解決數(shù)據(jù)插入異常、刪除異常,保證數(shù)據(jù)完整性(即正確性和一致性)和存儲效率。但是把數(shù)據(jù)庫分解得越多,就會造成查詢時的時間浪費(fèi)。通常認(rèn)為當(dāng)一個關(guān)系模式可以達(dá)到3NF(第三范式)或BCNF時,就具有了合理的結(jié)構(gòu)及良好的性能。當(dāng)關(guān)系規(guī)范化達(dá)到BCNF時, 雖然可以消除數(shù)據(jù)冗余太異常, 但卻可能會破壞了數(shù)據(jù)語義。所以,我們在設(shè)計時要先盡可能設(shè)計為BCNF,如果這時BCNF不到保持函數(shù)依賴的要求,破壞了數(shù)據(jù)語義,就應(yīng)該則降低為3NF。在這里,3NF是指所有的非主屬性都完全依賴主屬性且不傳遞于主屬性。一般情況下當(dāng)數(shù)據(jù)庫符合3NF后,通常就能很好的達(dá)到關(guān)系模式規(guī)范化的目的,它可以從根本上消除了數(shù)據(jù)冗余和數(shù)據(jù)不一致的問題。當(dāng)然,使用了第三范式設(shè)計數(shù)據(jù)庫后,還需要對表或者相關(guān)數(shù)據(jù)的結(jié)構(gòu)及性能進(jìn)行全面調(diào)整和優(yōu)化。
2 采用視圖方式
在一些數(shù)據(jù)量較大的表中,可能只有小部分?jǐn)?shù)據(jù)會被訪問,而且是被頻繁的訪問。這時,我們就可以采用視圖方式,把這部分?jǐn)?shù)據(jù)建立為視圖。有時,又會有一些數(shù)據(jù)需要針對不同角色有不同權(quán)限的開放,那么這些數(shù)據(jù)也可以做成視圖,并給視圖賦予不同的權(quán)限,這就可以從一定程度上保證了數(shù)據(jù)的安全性。
3 建立存儲過程
SQL Server 中存儲過程是SQL 語句和流程控制語句的集合。工作中,當(dāng)某些操作需要使用大量重復(fù)的計算時,我們就可以合理使用存儲過程儲存這些操作,完成軟件復(fù)用,實現(xiàn)高性能的數(shù)據(jù)操作。同時,我們在使用存儲過程后,還能能過隔離和加密的方法提高數(shù)據(jù)庫的安全性。
4 使用索引優(yōu)化數(shù)據(jù)庫
應(yīng)用數(shù)據(jù)庫中會存儲海量的數(shù)據(jù)表,人們對其做查詢操作時,若進(jìn)行全表掃描,會占用相當(dāng)長的時間。索引與字典的目錄類似,是數(shù)據(jù)庫中重要的數(shù)據(jù)結(jié)構(gòu),它可以通過關(guān)鍵值指向表中的數(shù)據(jù)行。通過合理地創(chuàng)建并使用索引,可以避免上述全表掃描,提高數(shù)據(jù)查詢的效率,可以減少由于連接造成的資源浪費(fèi),優(yōu)化數(shù)據(jù)庫性能。我們可以在表或視圖的一列或是多列上建索引,也可以在兩列或多列上建立復(fù)合索引。但是,索引在數(shù)據(jù)庫中會占用存儲空間,會犧牲系統(tǒng)性能,會在時間和空間方面帶來負(fù)面影響,因為表越大,索引也就越大。當(dāng)一個含有索引的表中數(shù)據(jù)行被更新時,索引也同樣需要更新,需要及時反映數(shù)據(jù)的變化。在含有索引的表中進(jìn)行插入、更新和刪除的操作時,速度可能會被影響。所以,在創(chuàng)建索引時必須考慮實際數(shù)據(jù)庫的查詢需求,以實現(xiàn)基于索引的數(shù)據(jù)庫優(yōu)化。
在建立索引時,應(yīng)該找到平衡點(diǎn),注意以下問題:
(1)如果處理的關(guān)系表比較小, 就不需要建立索引。因為直接遍歷整個表用的時間并不多, 建立索引反而加重了系統(tǒng)負(fù)擔(dān)。
(2)若表里的數(shù)據(jù)常會頻繁更新, 那么維護(hù)索引也將非常頻繁, 如果這些工作量超出了索引帶給我們的查詢優(yōu)勢, 則還不如不使用索引。
(3)索引分為聚集索引和非聚集索引。聚集索引的物理存儲按照索引排序。非聚集索引的物理存儲不按照索引排序。聚集索引在插入數(shù)據(jù)的時候,所花費(fèi)在“物理存儲的排序” 時間上較長,但查詢數(shù)據(jù)的速度會比查詢非聚集數(shù)據(jù)的速度快。在建立時應(yīng)考慮:
(4)不在 where 子句中進(jìn)行表達(dá)式運(yùn)算操作(如加減乘除)及函數(shù)操作。因為上述操作會使查詢放棄使用索引。
(5)創(chuàng)建及使用觸發(fā)器和存儲過程時,開始處進(jìn)行“SET NOCOUNT ON” 的設(shè)置,結(jié)束時進(jìn)行“SET NOCOUNT OFF” 設(shè)置,以減少服務(wù)器向客戶機(jī)發(fā)送信息造成的空間上和時間上的浪費(fèi)。
(6)盡量分解大事務(wù)為小事務(wù),提高系統(tǒng)的并發(fā)能力。
(7)小范圍內(nèi)進(jìn)行查詢時,子查詢會比連接查詢效率高。子查詢是指在WHERE或HAVING子句中又包含了一個SELECT語句。
例如,SELECT * FROM 課程表 WHERE 報名人數(shù)>(SELECT AVG(報名人數(shù)) FROM 課程表)
語句在執(zhí)行時由內(nèi)到外逐層執(zhí)行,小范圍內(nèi)效率較高。但如果大范圍內(nèi)使用了嵌套,且查詢嵌套層次越多, 效率越低, 子查詢會比連接查詢效率低。
(8)如果IN能用BETWEEN代替就用BETWEEN。因為BETWEEN會使用索引,但I(xiàn)N不會用索引。
(9)FROM子句中選擇合適的表序
SQL語句FROM子句中的表名有時會是多張表, SQL Server在對表名進(jìn)行解析時,會按照自右至左的順序處理,也就是寫在最后的表將被最先處理。所以,若FROM子句中包含多表則應(yīng)該選擇記錄行最少的表要寫在FROM子句的最后。
6 結(jié)論
優(yōu)化數(shù)據(jù)庫可以明顯提高計算機(jī)系統(tǒng)效率,具有非常深遠(yuǎn)的意義。在數(shù)據(jù)庫設(shè)計階段對邏輯結(jié)構(gòu)進(jìn)行合理化優(yōu)化,可獲得系統(tǒng)的較小開銷,從根本上提高系統(tǒng)的整體性能。