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