通過(guò)自定義函數(shù)提高服務(wù)器性能
導(dǎo)讀:在應(yīng)用程序開(kāi)發(fā)中,可以通過(guò)函數(shù)來(lái)提高系統(tǒng)的性能與代碼的重復(fù)利用。在SQL Server數(shù)據(jù)庫(kù)中也可以通過(guò)自定義函數(shù)來(lái)提高服務(wù)器的性能。用戶(hù)自定義函數(shù)可以從外部接受必要的參數(shù),并在內(nèi)部執(zhí)行一些復(fù)雜的操作,最后返回正確的結(jié)果。這項(xiàng)技術(shù)的出現(xiàn)很大程度上簡(jiǎn)便了人們的操作,使工作人員的工作輕松很多。
在數(shù)據(jù)庫(kù)開(kāi)發(fā)中,筆者強(qiáng)烈建議數(shù)據(jù)庫(kù)管理員要多用用函數(shù)。只要能夠通過(guò)函數(shù)來(lái)實(shí)現(xiàn)的功能,那么就要用函數(shù)。或許大家還不明白其中的原因。沒(méi)有關(guān)系,現(xiàn)把這個(gè)原則刻在心中,然后筆者再跟大家解釋其中的奧妙。
一、利用函數(shù)來(lái)實(shí)現(xiàn)業(yè)務(wù)邏輯的優(yōu)勢(shì)
1、 函數(shù)的執(zhí)行速度比普通的SQL代碼要快。
在同等條件下,實(shí)現(xiàn)同樣功能的SQL代碼與把SQL代碼定義成函數(shù),后者的執(zhí)行性能要比前者高許多。這主要是因?yàn)樵跀?shù)據(jù)庫(kù)中,用戶(hù)自定義函數(shù)通過(guò)緩存計(jì)劃并在重執(zhí)行時(shí)重用它來(lái)降低SQL代碼的編譯開(kāi)銷(xiāo)。如現(xiàn)在在數(shù)據(jù)庫(kù)中需要實(shí)現(xiàn)一個(gè)功能,要返回企業(yè)在職員工每天遲到或者曠工的人員信息。這個(gè)功能即可以每天通過(guò)一個(gè)SQL代碼來(lái)實(shí)現(xiàn)。也可以把實(shí)現(xiàn)這個(gè)查詢(xún)的SQL代碼封裝成一個(gè)函數(shù),然后應(yīng)用程序通過(guò)調(diào)用這個(gè)函數(shù)來(lái)實(shí)現(xiàn)這個(gè)需求。如果通過(guò)SQL代碼來(lái)實(shí)現(xiàn)的話(huà),每天查詢(xún)一次,數(shù)據(jù)庫(kù)都需要重新編譯并優(yōu)化這條SQL語(yǔ)句。而如果通過(guò)函數(shù)來(lái)調(diào)用的話(huà),則不需要重新解析和重新優(yōu)化。因?yàn)槠鋱?zhí)行計(jì)劃只要運(yùn)行過(guò)一次,就會(huì)在數(shù)據(jù)緩存中保存下來(lái)。下次需要調(diào)用這個(gè)函數(shù)的話(huà),則直接調(diào)用緩存中執(zhí)行計(jì)劃即可。可見(jiàn),通過(guò)函數(shù)來(lái)實(shí)現(xiàn)某些常用的功能,可以避免重復(fù)的解析與優(yōu)化,縮短執(zhí)行時(shí)間,提高數(shù)據(jù)庫(kù)性能。
2、 模塊化設(shè)計(jì)提高數(shù)據(jù)庫(kù)與應(yīng)用程序開(kāi)發(fā)性能。
如上面這個(gè)例子,企業(yè)剛開(kāi)始的時(shí)候可能需要查詢(xún)遲到與曠工人員的編號(hào)、姓名、職位、事由等信息。但是后來(lái)用戶(hù)的需求發(fā)生了改變,他們希望在這些信息的基礎(chǔ)上,還能夠帶出當(dāng)月累計(jì)遲到或者曠工的次數(shù)、是否有正當(dāng)手續(xù)等信息。如果在數(shù)據(jù)庫(kù)與應(yīng)用程序設(shè)計(jì)開(kāi)發(fā)的時(shí)候,是通過(guò)SQL代碼來(lái)實(shí)現(xiàn)這個(gè)功能的。那么此時(shí)筆者非常不幸的告訴大家,要實(shí)現(xiàn)這個(gè)需求的話(huà),必須修改源程序中嵌入的SQL代碼。這是一件非常麻煩的工作。但是如果通過(guò)函數(shù)來(lái)實(shí)現(xiàn)的話(huà),則應(yīng)用程序的源代碼基本上不需要更改。而只需要在數(shù)據(jù)庫(kù)中更改這個(gè)函數(shù)的代碼。這筆更改應(yīng)用程序代碼要簡(jiǎn)單的多,時(shí)間也可以短許多。
另外,可能不僅一個(gè)地方需要用到這個(gè)SQL代碼。在日常的查詢(xún)中,在員工的績(jī)效考核系統(tǒng)中,在工資核算系統(tǒng)中都需要這些內(nèi)容。如果用普通的SQL代碼來(lái)實(shí)現(xiàn)的話(huà),則在各個(gè)作業(yè)中都需要重復(fù)的書(shū)寫(xiě)這些代碼。顯然這個(gè)工作量非常的大。最要命的是,若以后用戶(hù)需求更改了的話(huà),需要同時(shí)修改多個(gè)地方的代碼。顯然通過(guò)SQL代碼來(lái)實(shí)現(xiàn)某些需求的話(huà),代碼的重復(fù)利用程度不高。這會(huì)影響數(shù)據(jù)庫(kù)的開(kāi)發(fā)效率。而通過(guò)函數(shù)來(lái)實(shí)現(xiàn)的話(huà),又有另一番新天地。因?yàn)橹恍枰獎(jiǎng)?chuàng)建一次函數(shù)并將其存儲(chǔ)在數(shù)據(jù)庫(kù)中,那么應(yīng)用程序中就可以進(jìn)行多次重復(fù)調(diào)用。即使需求有改變的話(huà),只需要更改函數(shù),那么其他各個(gè)作業(yè)的功能也會(huì)相應(yīng)的更改。
可見(jiàn)利用函數(shù)來(lái)實(shí)現(xiàn)功能,不僅可以提高數(shù)據(jù)庫(kù)運(yùn)行性能,而且還可以提高數(shù)據(jù)庫(kù)與應(yīng)用程序的開(kāi)發(fā)效率。
3、 減少網(wǎng)絡(luò)流量提高數(shù)據(jù)庫(kù)運(yùn)行性能。
如果利用函數(shù)來(lái)實(shí)現(xiàn)某些功能的話(huà),則還可以明顯的減少網(wǎng)絡(luò)流量。如上面這個(gè)需要,要統(tǒng)計(jì)員工當(dāng)月的遲到、早退、曠工次數(shù)。如果通過(guò)SQL代碼來(lái)實(shí)現(xiàn)的話(huà),則需要先把員工當(dāng)月每次遲到、早退、曠工的記錄返回到應(yīng)用程序中,然后再在應(yīng)用程序中進(jìn)行相關(guān)的統(tǒng)計(jì)。但是如果通過(guò)函數(shù)來(lái)實(shí)現(xiàn)這個(gè)功能的話(huà),則處理方式就不一樣了。利用函數(shù)來(lái)實(shí)現(xiàn)的話(huà),是在數(shù)據(jù)庫(kù)中統(tǒng)計(jì)好相關(guān)的結(jié)果,如員工遲到的次數(shù)等等。然后直接把這個(gè)結(jié)果返回給應(yīng)用程序。也就是說(shuō),用戶(hù)最終需要的是一個(gè)統(tǒng)計(jì)結(jié)果。而通過(guò)SQL代碼來(lái)實(shí)現(xiàn)的時(shí)候,數(shù)據(jù)庫(kù)需要把員工遲到、曠工等違紀(jì)信息的明細(xì)返回給應(yīng)用程序。而通過(guò)函數(shù)來(lái)實(shí)現(xiàn)的話(huà),則只是把最后的統(tǒng)計(jì)結(jié)果返回給應(yīng)用程序。顯然利用函數(shù)來(lái)實(shí)現(xiàn)其網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)量要少的多。這對(duì)于網(wǎng)絡(luò)帶寬受到限制的企業(yè)來(lái)說(shuō),可以通過(guò)這種方式輕而易舉的縮短用戶(hù)的等待時(shí)間。如果相關(guān)的記錄比較多,或者用戶(hù)需要通過(guò)互聯(lián)網(wǎng)遠(yuǎn)程訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)的時(shí)候,這個(gè)效果特別明顯。
二、Transact-SQL 函數(shù)與CLR 函數(shù),該用哪一種?
在SQL數(shù)據(jù)庫(kù)中,不僅可以利用數(shù)據(jù)庫(kù)自帶的Transact-SQL語(yǔ)言來(lái)編寫(xiě)函數(shù),而且還可以使用Microsoft .NET Framework 編程語(yǔ)言來(lái)編寫(xiě)函數(shù)。這在很大程度上提高了函數(shù)能夠?qū)崿F(xiàn)的功能。不過(guò)兩種語(yǔ)言在不同的情況下使用,對(duì)于數(shù)據(jù)庫(kù)的性能的影響是不同的。為此數(shù)據(jù)庫(kù)設(shè)計(jì)與開(kāi)發(fā)人員必須了解這兩種語(yǔ)言的差異,并在合適的情況下選擇合適的語(yǔ)言。這有利于提高數(shù)據(jù)庫(kù)的性能。在SQLServer數(shù)據(jù)庫(kù)中,把利用Microsoft .NET Framework 編程語(yǔ)言來(lái)實(shí)現(xiàn)的函數(shù),叫做CLR函數(shù)。如CRL表量值函數(shù)用來(lái)返回單個(gè)結(jié)果的值,如字符串、數(shù)字等等。那么到底還如何進(jìn)行選擇呢?筆者的如下幾個(gè)建議或許能夠幫助大家。
第一個(gè)建議:客戶(hù)端運(yùn)行OR服務(wù)器運(yùn)行?
以前在數(shù)據(jù)庫(kù)部署的時(shí)候,由于客戶(hù)端配置的問(wèn)題,往往把所有的應(yīng)用都放在服務(wù)器上實(shí)現(xiàn)。如此的話(huà),只要提高服務(wù)器的配置即可。但是隨著數(shù)據(jù)庫(kù)應(yīng)用越來(lái)越復(fù)雜,把所有的擔(dān)子都?jí)涸跀?shù)據(jù)庫(kù)服務(wù)器上,已經(jīng)讓數(shù)據(jù)庫(kù)服務(wù)器超負(fù)荷運(yùn)行了。隨著客戶(hù)端硬件配置的提高,為此把一些運(yùn)行時(shí)間比較長(zhǎng)的作業(yè)放到客戶(hù)端來(lái)運(yùn)行,未嘗不是分?jǐn)偡?wù)器壓力的一種好方法。如果數(shù)據(jù)庫(kù)設(shè)計(jì)與開(kāi)發(fā)人員有這種想法的話(huà),那么在選擇使用Transact-SQL 函數(shù)還是CLR 函數(shù)的問(wèn)題上,就有了方向。Transact-SQL 函數(shù)與CLR 函數(shù)都可以在服務(wù)器上運(yùn)行。在服務(wù)器上運(yùn)行函數(shù)的話(huà),可以將代碼與數(shù)據(jù)靠近在一起,以減少不必要的網(wǎng)絡(luò)流量。但是就如同上面所說(shuō)的,有時(shí)會(huì)數(shù)據(jù)庫(kù)設(shè)計(jì)人員出于整體性能的考慮,不得不把一些運(yùn)行時(shí)間比較長(zhǎng)或者硬件資源耗用量比較大的作業(yè)放在客戶(hù)端上執(zhí)行。但是到目前為止,Transact-SQL 函數(shù)只能夠在服務(wù)器端執(zhí)行,CLR 函數(shù)的話(huà)不僅可以在服務(wù)器端運(yùn)行而且還可以在客戶(hù)端上執(zhí)行。所以,如果要把某個(gè)復(fù)雜的作業(yè)放在客戶(hù)端上運(yùn)行,而這個(gè)作業(yè)又需要調(diào)用某個(gè)函數(shù)的話(huà),那么在這種情況下就需要采用CLR 函數(shù)。
第二個(gè)建議:業(yè)務(wù)邏輯的復(fù)雜性?
利用函數(shù)來(lái)實(shí)現(xiàn)的功能,即可以是才十幾行代碼的作業(yè),也可以是包含幾百條業(yè)務(wù)邏輯的復(fù)雜功能。在編寫(xiě)函數(shù)的時(shí)候,到底是采用Transact-SQL 函數(shù)還是CLR 函數(shù),還需要看看其業(yè)務(wù)邏輯的復(fù)雜性。因?yàn)門(mén)ransact-SQL代碼雖然也可以實(shí)現(xiàn)一些復(fù)雜的功能,但是其畢竟不是屬于專(zhuān)業(yè)的開(kāi)發(fā)語(yǔ)言。當(dāng)業(yè)務(wù)邏輯比較復(fù)雜的時(shí)候,Transact-SQL代碼開(kāi)發(fā)和執(zhí)行的時(shí)候,效率并不是很好。如現(xiàn)在要給用戶(hù)利用隨機(jī)數(shù)生成密碼。在這個(gè)功能上,利用Transact-SQL代碼也可以實(shí)現(xiàn),但是其代碼會(huì)很長(zhǎng)。而利用CLR函數(shù)來(lái)實(shí)現(xiàn)的話(huà),則只需要簡(jiǎn)單的幾行。可見(jiàn)這個(gè)代碼的編寫(xiě)量上就有很多的差別。代碼量一增加,那么后續(xù)維護(hù)的工作量也就越大。
為此為了提高函數(shù)的開(kāi)發(fā)效率,對(duì)于業(yè)務(wù)邏輯比較復(fù)雜,并且可能會(huì)占用服務(wù)器比較多的CPU或者內(nèi)存資源的函數(shù),最好采用CLR函數(shù)來(lái)實(shí)現(xiàn)。這不僅可以簡(jiǎn)化函數(shù)的開(kāi)發(fā),而且在有需要的時(shí)候,還可以把這個(gè)函數(shù)放在客戶(hù)端上去職執(zhí)行,一舉多得。故在判斷到底采用哪種函數(shù)為好的話(huà),還需要考慮其業(yè)務(wù)邏輯的復(fù)雜性與硬件資源的耗用情況。
總的來(lái)說(shuō),在大部分情況下,Transact-SQL 函數(shù)與CLR 函數(shù)是通用的。但是為了取得更好的性能,可以根據(jù)以上的幾個(gè)建立來(lái)判斷到底利用哪種類(lèi)型的函數(shù)。另外,如果采用擴(kuò)展存儲(chǔ)過(guò)程的話(huà),最好也是采用CLR函數(shù)。因?yàn)閿U(kuò)展存儲(chǔ)過(guò)程與CLR函數(shù)的兼容性比較好。但是CLR函數(shù)是利用C#等編程語(yǔ)言開(kāi)發(fā)的,對(duì)于一些數(shù)據(jù)庫(kù)管理員來(lái)說(shuō)可能有一定的難度。這也可以說(shuō)明,未來(lái)的數(shù)據(jù)庫(kù)開(kāi)發(fā)人員,往往需要多掌握幾門(mén)語(yǔ)言,才能夠勝任。光靠SQL語(yǔ)言往往并能夠完成數(shù)據(jù)庫(kù)的全部設(shè)計(jì)與開(kāi)發(fā)工作。因?yàn)闃I(yè)務(wù)需求對(duì)數(shù)據(jù)庫(kù)性能方面的要求越來(lái)越高。多門(mén)語(yǔ)言的結(jié)合使用,有利于數(shù)據(jù)庫(kù)開(kāi)發(fā)者設(shè)計(jì)性能更高的數(shù)據(jù)庫(kù)應(yīng)用系統(tǒng),從而給用戶(hù)更快的享受,提高用戶(hù)滿(mǎn)意度。關(guān)于通過(guò)自定義函數(shù)提高服務(wù)器性能的問(wèn)題就為大家講述到這,希望文中的內(nèi)容能夠幫到大家。
【編輯推薦】