6

SQL Server 2012に各テナントの行がtenant_id列(別名Shared Database, Shared Schemaという方法)で識別されるマルチテナントデータベースがあります。一部のテナント、特に新しいテナントでは行がほとんどなく、他のテナントでは行がほとんどありません。マルチテナントSQL Serverデータベースとパラメータスニッフィング

SQL Serverのクエリオプティマイザは、通常、最初の実行中に提供されたパラメータに基づいてクエリプランを作成し、別のパラメータが提供されていても将来のすべてのクエリに対してこのプランを再利用します。これはparameter sniffingとして知られています。

データベースで問題が発生するのは、小さなテナントを指すパラメータに基づいてSQL Serverがこれらのプランを構築することがあります。テナントは問題なく動作しますが、キャッシュされたプランを大きなテナントに再適用すると、壊滅的に(通常は実際にタイムアウトする)。通常は、大規模なテナントのうちの1人がタイムアウトエラーの発生について私たちに連絡した場合にのみ、システムに入り、すべてのクエリプランを手動でフラッシュして修正する必要があります。

SQL Serverがクエリプラン()をキャッシュしないようにするために使用できるクエリヒントがありますが、クエリが呼び出されるたびにクエリプランが再生成されるため、余分なオーバーヘッドが発生します。もう1つの問題は、クエリでOPTIMIZE FOR UNKNOWNヒントを指定できないEntity Frameworkを使用していることです。

したがって、パラメータスニッフィングに関してマルチテナントデータベースのベストプラクティスは何ですか?すべてのクエリでパラメータスニッフィングを指定しなくても、データベース全体でパラメータスニッフィングを無効にする方法はありますか?もしそうなら、それは最善のアプローチですか?他の方法でデータを分割する必要がありますか?私が考えていない他のアプローチがありますか?

+0

AFAIK、これを修正するには、ストアドプロシージャを使用する必要があります。あなたの周りにあなたを得ることができるEFのいくつかの機能がない限り。 – RBarryYoung

+0

'OPTIMIZE FOR UNKNOWN'には、あなたが記述する動作はありません。あなたは 'OPTION(RECOMPILE) 'と混同しています。エンタープライズ版を使用している場合は、計画ガイドを参照してヒントを提供できます。または、トレースフラグ(4136)が[パラメータスニッフィングを完全に無効にする](http://support.microsoft.com/kb/980653)ですが、**インスタンス**データベースには適用されません。 –

答えて

3

私は同様の問題があった、とこのように私のパラメータを渡すことによって成功し、それを解決した: に渡されたパラメータごとに1-1基づいてローカル変数を作成し、他の言葉で

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] 

SPのロジック内でこれらの新しい変数を参照するだけです。おそらく、SQL Serverが私のためにできるいくつかの最適化を見逃しているかもしれませんが、最も重要なのは、パラメタがスニッフィングするときに得られる本当に恐ろしいパフォーマンスを逃してしまうことです。

あなたの場合、これはマルチテナントID(すべてのSPのパラメータと見なします)のためのものです。可能であればSQLサーバーが残りのパラメーターを最適化できるようにします。

+0

これは本質的にOPTIMIZE FOR UNKNOWNクエリのヒントと同じものです。残念ながら、生成されているクエリを変更することはできないため、どちらのアプローチもEntity Frameworkで使用することはできません。 – Mike

関連する問題