是否應該使用存儲過程?


在許多關系型數據庫教材中,都推薦使用存儲過程,並列舉種種好處。比如以下來自微軟官方文檔的解釋:

使用存儲過程的好處

下表介紹了使用過程的一些好處。
減少了服務器/客戶端網絡流量
過程中的命令作為代碼的單個批處理執行。 這可以顯著減少服務器和客戶端之間的網絡流量,因為只有對執行過程的調用才會跨網絡發送。 如果沒有過程提供的代碼封裝,每個單獨的代碼行都不得不跨網絡發送。
更強的安全性
多個用戶和客戶端程序可以通過過程對基礎數據庫對象執行操作,即使用戶和程序對這些基礎對象沒有直接權限。 過程控制執行哪些進程和活動,並且保護基礎數據庫對象。 這消除在了單獨的對象級別授予權限的要求,並且簡化了安全層。
可在 CREATE PROCEDURE 語句中指定 EXECUTE AS 子句以便實現對其他用戶的模擬,或者使用戶或應用程序無需針對基礎對象和命令的直接權限,即可執行某些數據庫活動。 例如,某些操作(如 TRUNCATE TABLE)沒有可授予的權限。 若要執行 TRUNCATE TABLE,用戶必須對指定表具有 ALTER 權限。 授予用戶對表的 ALTER 權限可能不是最佳方法,因為用戶將擁有超出截斷表的能力的權限。 通過將 TRUNCATE TABLE 語句納入模塊中並指定該模塊作為一個有權修改表的用戶執行,您可以將截斷表的權限擴展至授予其對模塊的 EXECUTE 權限的用戶。
在通過網絡調用過程時,只有對執行過程的調用是可見的。 因此,惡意用戶無法看到表和數據庫對象名稱、嵌入自己的 Transact-SQL 語句或搜索關鍵數據。
使用過程參數有助於避免 SQL 注入攻擊。 因為參數輸入被視作文字值而非可執行代碼,所以,攻擊者將命令插入過程內的 Transact-SQL 語句並損害安全性將更為困難。
可以對過程進行加密,這有助於對源代碼進行模糊處理。 有關詳細信息,請參閱 SQL Server Encryption。
代碼的重復使用
任何重復的數據庫操作的代碼都非常適合於在過程中進行封裝。 這消除了不必要地重復編寫相同的代碼、降低了代碼不一致性,並且允許擁有所需權限的任何用戶或應用程序訪問和執行代碼。
更容易維護
在客戶端應用程序調用過程並且將數據庫操作保持在數據層中時,對於基礎數據庫中的任何更改,只有過程是必須更新的。 應用程序層保持獨立,並且不必知道對數據庫布局、關系或進程的任何更改的情況。
改進的性能
默認情況下,在首次執行過程時將編譯過程,並且創建一個執行計划,供以后的執行重復使用。 因為查詢處理器不必創建新計划,所以,它通常用更少的時間來處理過程。
如果過程引用的表或數據有顯著變化,則預編譯的計划可能實際上會導致過程的執行速度減慢。 在此情況下,重新編譯過程和強制新的執行計划可提高性能。

個人猜測這個觀點是從傳統OLTP系統性能優化的角度考慮的。由於OLTP的操作往往需要短平快,傳輸的數據量不大。比如需要返回的一行記錄可能只有幾十個字節,不用存儲過程的話,為了獲取這幾十個字節卻需要向服務器發送1KB甚至更長的SQL語句,性價比實在太不理想。當然也有代碼邏輯重用,執行計划重用等等其它方面的考慮,在此先不討論。

但是在OLAP系統中,一條SQL語句往往會返回大量數據,並運行較長時間。這種情況下,是否使用存儲過程對性能的影響就顯得不那么明顯。而且要注意的是,實際項目開發決策需要參考很多方面,性能只是各種因素其中之一。使用存儲過程的話,開發過程中經常碰到以下比較頭痛的問題:

  1. 搞不清調用這個存儲過程的是哪個SSIS包,哪個SSRS報表,哪個SSAS數據視圖,哪個程序塊。一旦存儲過程需要更改,很難快速查清受影響的范圍。有的項目有自己的方法來解決這個問題,比如采用特定的命名規則之類的,然而非常高效通用的辦法還是比較少見。
  2. 雖然將數據庫代碼加入源代碼管理是比較推薦的做法,但仍然有許多項目由於種種客觀條件的限制難以做到這一點(抱歉,這樣說有點籠統,請自行體會)。在這樣的情況下,存儲過程代碼往往失於管理,不知道誰在什么時候修改了哪些存儲過程的哪些地方。這些問題的一個典型特征是在編碼行為上間接對項目組成員產生難以察覺的影響,例如有些人會形成“將舊代碼注釋掉並保留”的習慣以便於未來察看代碼的舊貌,有些人會在修改存儲過程之前備份數據庫,有些人則喜歡在修改存儲過程前創建一個副本。。。這些行為的根本問題,正是由於沒有對存儲過程進行源代碼管理。
  3. 許多小型項目缺乏嚴謹的權限管理,不能刪除不能修改的存儲過程常常被意外地刪除或者修改。

特別是對於長期的開發項目,代碼管理的重要性往往大於對性能的需求。因此我認為,針對上述問題,在OLAP環境中,一方面應該堅持將數據庫代碼加入源代碼管理,另一方面應該將SQL語句直接寫在調用方代碼里以便追蹤代碼變更的影響。

 

歡迎加入SQL Server精英群參與技術交流


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM