6

I have a multi-tenant database in SQL Server 2012 where each tenant's rows are identified by a tenant_id column (aka the Shared Database, Shared Schema approach). Some tenants, particularly the newer ones, have very few rows, while others have many.

SQL Server's query optimizer normally builds a query plan based on the parameters provided during its first execution, then re-uses this plan for all future queries even if different parameters are provided. This is known as parameter sniffing.

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

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

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

4

2 に答える 2

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 Id=@xAPBatchId.....etc.

つまり、渡されたパラメーターごとに 1 対 1 でローカル変数を作成し、SP のロジック内でそれらの新しい変数のみを参照します。SQL Server が実行できる最適化を見逃している可能性がありますが、最も重要なのは、パラメーター スニッフィングが開始されたときに得られる本当に恐ろしいパフォーマンスを見逃していることです。

あなたの場合、おそらくマルチテナントID(すべてのSPのパラメーターであると思いますか?)に対してのみこれを実行し、可能であればSQLサーバーに残りのパラメーターを最適化させることができます。

于 2012-10-19T17:43:01.223 に答える