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