6

我在SQL Server 2012中有一個多租戶數據庫,其中每個租戶的行由tenant_id列(又名Shared Database, Shared Schema方法)標識。有些租戶,特別是較新的租戶,行數很少,而其他租戶則有很多。多租戶SQL Server數據庫和參數嗅探

SQL Server的查詢優化器通常會生成基於它的第一個執行過程中所提供的參數的查詢計劃,然後重新使用該計劃,今後所有的查詢即便是有不同的參數。這被稱爲parameter sniffing

我們在數據庫中遇到的問題是,SQL Server有時會根據指向較小租戶的參數構建這些計劃,這對租戶來說工作正常,但是當它將緩存計劃重新應用到較大的租戶時,災難性地(通常事實上是超時)。通常我們對這種情況找出只有當我們的大租戶聯繫我們關於經歷超時錯誤之一,那麼我們就可以進入系統和手動刷新所有查詢計劃,以糾正它。

有一個查詢提示可以用來防止SQL Server緩存查詢計劃(OPTIMIZE FOR UNKNOWN),但這會導致一些額外的開銷,因爲每次調用查詢時都會重新生成查詢計劃。另外一個問題是,我們使用的是實體框架,它無法爲查詢指定OPTIMIZE FOR UNKNOWN提示。

所以,問題是 - 什麼是多租戶數據庫的最佳實踐方面的參數嗅探?有沒有辦法禁用參數嗅探數據庫範圍,而不必在每個查詢中指定它?如果是這樣,那是最好的辦法嗎?我應該以其他方式分割數據嗎?有沒有其他的方法我沒有想到?

+0

據我所知,您需要使用存儲過程來解決這個問題是。除非EF有一些功能可以幫助你解決這個問題。 – RBarryYoung

+0

「未優化的優化」不具備您描述的行爲。你用'OPTION(RECOMPILE)'混淆了它。如果您使用Enterprise Edition,則可以查看計劃指南以提供提示。或者是有跟蹤標誌(4136)爲[禁用參數完全嗅探(http://support.microsoft.com/kb/980653),但適用於** **實例不是數據庫。 –

回答

3

我有過類似的問題,並通過傳遞我的參數,這樣成功解決了這個問題:

CREATE PROCEDURE [dbo].[InsertAPCheck] 
@APBatchID int = Null, 
@BankAccountID int = Null 
AS 
    /* copy parameters to temporary variables */ 
    SELECT @xAPBatchId = APBatchId, @xBankAccountID = @BankAccountID 
. 
. 
/* now run the meat of your logic using the temp variables */ 
SELECT * FROM myTable where [email protected] 
換句話說

,在 傳遞的每個參數1-1的基礎上創建一個局部變量然後只在SP的邏輯範圍內引用這些新變量。我可能錯過了SQL Server可以爲我做的一些優化,但最重要的是我錯過了當參數嗅探開始時真正可怕的性能。

對您而言,或許您可以嘗試這只是爲了多租戶ID(我假設它是所有SP的參數?),並且讓SQL服務器優化其餘參數(如果可以的話)。

+0

這實質上就是OPTIMIZE FOR UNKNOWN查詢提示所做的。不幸的是,我不能在Entity Framework中使用這兩種方法,因爲我無法修改正在生成的查詢。 – Mike