2017-05-01 24 views
0

我最近在工作中被問到要執行許多SQL Server存儲過程「適應」。我可以管理,但我主要是一個.Net開發人員,所以我不知道什麼是好的做法,或者是否有更好的方法來做事情。有多個可選參數的存儲過程

簡而言之,就是這種情況。我們有許多腳本每晚運行以避免對生產造成任何影響。他們掃描多個數據庫(鏈接服務器和所有)以查找特殊情況並在發現這種情況時添加記錄。每個腳本都會在所有數據庫(包含數百萬條記錄)上執行此操作,並且有超過一百個以這種方式運行的腳本。

現在,我被要求更改這些腳本,以便他們可以接受參數並被稱爲「按需」(不再需要每晚運行)。簡單。

我在哪裏,猶豫,是他們希望調用SAME過程,但對於不同的場景,每個場景都會傳遞它自己的一組參數,然後查詢應該執行一些業務邏輯去執行那個特定的「場景」。

例如,存儲過程將具有這些輸入參數定義:

@PersonId, @OrderId, @OrderType, @RequestCode, .... 

和可能更多一些。

當存儲過程收到@PersonId時,我應該返回該人的所有特殊情況,但如果是@OrderType,那應該是所有情況,但是對於該特定類型。但是,如果它收到OrderId,存儲過程應該返回該訂單的所有特殊情況。如果提供了RequestCode,它應該返回與該代碼關聯的所有情況,針對每個人,所有要求。有4個場景需要處理,它們都應該返回相同的數據,但是針對不同的條件。

他們特別要求應該只有一個腳本(每個特殊情況)來處理所有可能性。

就像我說的那樣,現在腳本每晚都運行,整個數據庫沒有參數。

我建議將腳本轉換爲代碼,這樣我就可以使用所有好的模式,添加測試,隔離它們以及所有內容。如果我保留「sql方式」,我很害怕每一個小小的變化都意味着更多的測試,並且由於我們可以輕鬆訪問程序員,但是數據庫管理員是非常罕見的,有特殊情況按需檢測.NET(這是檢測請求將被調用的地方......),擁有一些類和接口應該更容易維護和發展,即使是初級。

請求不再運行在每條記錄上,並且沒有那麼多員工會提出這些請求,尤其是那些請求不會同時發生。所以我也沒有看到性能問題?

我是一名開發人員,所以我當然偏向於。但是,如果有一種很好的方式來滿足他們對我的要求(將所有內容保存在存儲過程中,有許多參數,條件和明顯的某種程度的業務邏輯),我也可以做得更好。

對不起,對於這篇較長的文章,特別感謝那些有時間留意一些建議的人!

編輯:假設我改編腳本以處理所有可能性,測試的主要影響是什麼,可以預見的可維護性是什麼?由於我沒有經驗,我認爲,對於這樣一個「可以做任何事情的魔術腳本」,調試,測試和一切都將是一場噩夢,但這裏的人們似乎忽略了它。但他們不是程序員,也不是數據庫管理員,所以我想提出一些理由,讓他們按照正確的方式做事情,無論是現在還是將來,即使這意味着開始時會有更高的成本。謝謝!

+3

讓單個存儲過程完成不同的事情是非常糟糕的設計。這就像在dotnet中創建一個方法,根據傳遞的參數完成不同的操作。就像你的編程代碼一樣,你希望你的程序做一件事,做得很好。 –

+0

我完全同意。我試圖從有經驗的數據庫管理員那裏得到很好的建議,所以我們可以提出一些要點,以便我們能夠很好地解決如何管理這些問題。謝謝。 –

+0

這可以歸結爲性能。將爲存儲過程創建一個執行計劃並存儲在緩存中。當你有多個像這樣的執行路徑時,它會完全破壞引擎一致性生成高效執行計劃的能力。所以即使這個計劃對於一組參數來說很好,但對另一個參數來說也是可怕的。但是,如果它存在,它將使用已存在於高速緩存中的計劃。如果有什麼可以創建一個程序作爲「驅動程序」,並讓它根據參數調用各種其他程序。這爲每條路徑提供了一個很好的計劃。 –

回答

0

讓單個存儲過程完成不同的事情是非常糟糕的設計。這就像在dotnet中創建一個方法,根據傳遞的參數完成不同的操作。就像你的編程代碼一樣,你希望你的程序做一件事,做得很好。

這歸結爲性能。將爲存儲過程創建一個執行計劃並存儲在緩存中。當你有多個像這樣的執行路徑時,它會完全破壞引擎一致性生成高效執行計劃的能力。所以即使這個計劃對於一組參數來說很好,但對另一個參數來說也是可怕的。但是,如果它存在,它將使用已存在於高速緩存中的計劃。如果有什麼可以創建一個程序作爲「驅動程序」,並讓它根據參數調用各種其他程序。這爲每條路徑提供了一個很好的計劃。

0

您爲您的問題添加了很多細節,但是,如果您問的是如何處理存儲過程中的可選參數,那麼一種方法是在where子句評估中包含缺少值。如果這些參數用於過濾數據,那麼此流程將起作用。我會發出警告,Mode,ProcessingType,Action,UpdateTypeOperation參數類型通常表示半透明操作。

要考慮的另一件事是查詢優化器如何處理參數。如果使用一組類似的參數多次調用存儲過程,那麼優化器可以選擇一個適用於第一個或最常用的參數集的查詢計劃。稍後,您可能會傳遞一個值,這是緩存計劃的最壞情況。這可能會導致您的「亞秒級」存儲過程無處不在,開始攪拌很長一段時間。您可以通過優化和編譯器提示來解決這個問題,但是,我建議您閱讀參數嗅探,以便在您從存儲過程中看到奇怪的性能時做好準備。

CREATE PROCEDURE MySPWithOptionalParams 
    (@P1 INT = NULL, 
     @P2 INT = NULL, 
     @P3 INT = NULL) 
AS 
    SELECT * 
    FROM MyTable 
    WHERE (@P1 IS NULL OR F1 = @P1) 
     AND (@P2 IS NULL OR F2 = @P2) 
     AND (@P3 IS NULL OR F3 = @P3) 
+0

謝謝。但我有可選參數,我可以做到這一點。我正在尋找的是根據這些參數調整腳本的好方法。正如肖恩在評論中提到的那樣,我害怕「可以做任何事情」的代碼,但是做得不好。 –

+0

我同意這種說法。 –