菜菜哥,我新接手了一個專案,看的我頭疼呀

業務有這麼複雜呀?

不是的,這個老專案完全是用儲存過程寫的,每個儲存過程都好幾百行

這樣呀,是夠頭疼的~

有沒有辦法幫我瞭解業務一下?

碰到這樣的情況,我真幫不了你了,你可以多埋怨幾句做的那個人~~~

儲存過程

儲存過程(Stored Procedure)是在大型資料庫系統中,一組為了完成特定功能的SQL 語句集,它儲存在資料庫中,一次編譯後永久有效,使用者通過指定儲存過程的名字並給出引數(如果該儲存過程帶有引數)來執行它。儲存過程是資料庫中的一個重要物件。

優勢

1. 可以減少程式在呼叫DB時候的資訊傳輸量(其實減少的只有Request的時候)

2. 儲存過程是預先優化和預編譯的,節省每次執行編譯的時間,所以一般情況下認為儲存過程的效能是優於sql語句的。

3. 對呼叫者可以隱藏資料庫的複雜性,將資料組裝的過程封裝。

4. 引數化的儲存過程可以防止SQL注入式攻擊,而且可以將Grant、Deny以及Revoke許可權應用於儲存過程。

5. 如果業務開發中,資料人員和業務程式碼人員是分離的,業務人員可以不用關心資料,直接呼叫儲存過程,更加面向分層開發設計理念。

劣勢

1. 儲存過程這種“一次優化,多次使用”的策略節省了每次執行時候編譯的時間,但也是該策略導致了一個致命的缺點:可能會使用錯誤的執行計劃。

2. 儲存過程難以除錯,雖然有些DB提供了除錯功能,但是一般的賬號根本就沒有那種許可權,更何況線上的資料庫不可能會給你除錯許可權的,再進一步就算能除錯效果也比程式的除錯效果要差很多。

3. 可移植性差,當碰到切換資料種類的時候,儲存過程基本就會歇菜。

4. 如果業務資料模型有變動,儲存過程必須跟著業務程式碼一起更改,如果是大型專案,這種改動是空前的,是要命的。

不推薦儲存過程

以上儲存過程的優缺點,你隨便一下網路就可能查到,表面看來儲存過程的優勢還是不少的,這也說明為什麼老一輩程式設計師有很多喜歡寫儲存過程。但是隨著軟體行業業務日益複雜化,儲存過程現在在複雜業務面前其實有點有心無力。

菜菜在業務中並不推薦使用儲存過程,辯駁請留言。


1. 採用儲存過程操作資料在網路資料量傳輸上確實比直接使用sql語句要少很多,但這通常並不是操作資料系統性能的瓶頸,在一次操作資料的過程中,假設用時100毫秒,採用儲存過程節省資料傳輸時間0.5毫秒(就算是5毫秒),我覺得這點時間基本可以忽略。

2. 儲存過程是隻優化一次的,這有時候恰恰是個缺陷。有的時候隨著資料量的增加或者資料結構的變化,原來儲存過程選擇的執行計劃也許並不是最優的了,所以這個時候需要手動干預或者重新編譯了,而什麼時候執行計劃不是最優的了這個平衡點,預先無法知曉,這就導致了有些應用突然會變慢,程式設計師處於懵逼的狀態。

3. 儲存過程確實可以對呼叫方隱藏資料庫的細節,但是這種業務程式碼人員和資料庫設計人員是兩個團隊的情況又有多少呢,如果真是兩個團隊,那業務就需要兩個團隊來理解和溝通,我想溝通的成本也一定很高,而且分歧更容易產生。


菜菜認為資料庫就應該做它最擅長的事情:儲存相關。我不止一次的看過把業務寫在儲存過程的情況,程式程式碼層面真是薄薄的貧血層,就是一個數據的透傳。我不贊同這種寫法,因為我就接手過這樣的程式,令我頭疼的不是業務,而是看著好幾千行的儲存過程熟悉業務,關鍵還沒有除錯的許可權(線上更不能除錯)。


一個業務系統的設計往往需要你從資料庫的層面抽離出來,把主要精力放在業務模型的設計上,在程式層面體現業務邏輯,而不是把業務邏輯都交給資料層面的管理者。前幾天我排查過一個“Bug”:儲存過程是輸入引數是一個主鍵id的列表字串,長度居然是 nvarchar(max),主要功能是根據id列表查詢資料。我想說的是就算你是max的長度,也有超長的可能性發生,因為業務方傳輸什麼引數,引數什麼長度是你DB無法控制的,所以這類的業務一定要放在程式中做處理,而不是懷著僥倖心裡丟給DB。


如果是抱著儲存過程效能高的心態的話,我到時覺你這是誤入歧途,菜菜認為儲存過程從來都不是提高效能的關鍵,反而系統的架構,快取的設計,資料一致性更是系統關鍵問題。

儲存過程通常是一種解決方案,但是通常情況下不是唯一的解決方案,在選擇儲存過程作為方案前,請確保他們是正確的選擇。

最後秀一波儲存過程吧

THE END


●程式設計師修神之路--問世間非同步為何物?
●程式設計師修神之路--提高網站的吞吐量