Sql-Server
儲存過程與內聯 SQL
我知道儲存過程通過執行路徑(比應用程序中的內聯 sql)更有效。但是,當被按下時,我對原因並不是很清楚。
我想知道這方面的技術原因(以後我可以向別人解釋)。
誰能幫我制定一個好的答案?
我相信這種觀點在某一時刻是正確的,但在目前版本的 SQL Server 中並非如此。整個問題在於,在過去,即席 SQL 語句無法正確優化,因為 SQL Server 只能在批處理級別進行優化/編譯。現在我們有了語句級優化,因此來自應用程序的正確參數化查詢可以利用與儲存過程中嵌入的查詢相同的執行計劃。
由於以下原因,我仍然更喜歡 DBA 方面的儲存過程(其中一些可能會對性能產生巨大影響):
- 如果我有多個應用程序重複使用相同的查詢,儲存過程會封裝該邏輯,而不是在不同的程式碼庫中多次亂扔相同的即席查詢。重複使用相同查詢的應用程序也可能會受到計劃記憶體膨脹的影響,除非它們被逐字複製。即使大小寫和空格的差異也可能導致儲存同一計劃的多個版本(浪費)。
- 我可以檢查和排除查詢正在做什麼,而無需訪問應用程序原始碼或執行昂貴的跟踪來準確查看應用程序在做什麼。
- 我還可以控制(並提前知道)應用程序可以執行哪些查詢、可以訪問哪些表以及在什麼上下文中,等等。如果開發人員在他們的應用程序中臨時編寫查詢,他們要麼必須每次他們需要使用我不知道或無法預測的桌子時,或者如果我不那麼負責任/熱情和/或安全意識不強,我就會拉扯我的襯衫袖子,我只是要宣傳一下使用者到 dbo,這樣他們就不會再打擾我了。通常,當開發人員數量超過 DBA 或 DBA 很固執時,就會這樣做。最後一點是我們的壞事,我們需要更好地提供您需要的查詢。
- 在相關的說明中,一組儲存過程是一種非常簡單的方法,可以準確地清點我的系統上可能正在執行的查詢。一旦允許應用程序繞過過程並送出自己的臨時查詢,為了找到它們,我必須執行涵蓋整個業務週期的跟踪,或者解析所有應用程式碼(再次,我可能無權訪問)來查找任何看起來像查詢的內容。能夠查看儲存過程列表(並 grep 單個源,
sys.sql_modules
用於對特定對象的引用)使每個人的生活變得更加輕鬆。- 我可以花更多的時間來防止 SQL 注入;即使我接受輸入並使用動態 SQL 執行它,我也可以控制很多允許發生的事情。在建構內聯 SQL 語句時,我無法控制開發人員在做什麼。
- 我可以優化查詢(或查詢),而無需訪問應用程序原始碼、進行更改的能力、有效執行此操作的應用程序語言知識、重新編譯和重新部署的權限(不用擔心麻煩)應用程序等。如果應用程序是分佈式的,這尤其成問題。
- 我可以強制儲存過程中的某些設置選項,以避免個別查詢受到應用程序中的某些慢速,SSMS 中的快速?問題。這意味著對於呼叫臨時查詢的兩個不同應用程序,一個可能有
SET ANSI_WARNINGS ON
,另一個可能有SET ANSI_WARNINGS OFF
,並且它們每個都有自己的計劃副本。他們獲得的計劃取決於使用的參數、到位的統計資訊等。在每種情況下第一次呼叫查詢時,這可能會導致不同的計劃,從而導致非常不同的性能。- 與某些 ORM 不同,我可以控制諸如數據類型和如何使用參數之類的東西 - 一些早期版本的東西(如 EF)會根據參數的長度參數化查詢,所以如果我有一個參數 N’Smith’ 和另一個 N’ Johnson’ 我會得到兩個不同版本的計劃。他們已經解決了這個問題。他們已經解決了這個問題,但還有什麼問題?
- 我可以做一些 ORM 和其他“有用的”框架和庫還不能支持的事情。
話雖如此,這個問題可能會引發比技術辯論更多的宗教爭論。如果我們看到這種情況發生,我們可能會關閉它。