6

Ho un database multi-tenant in SQL Server 2012 in cui le righe di ciascun tenant sono identificate da una colonna tenant_id (ovvero l'approccio Shared Database, Shared Schema). Alcuni inquilini, in particolare quelli più recenti, hanno poche file, mentre altri ne hanno molti.Database multi-tenant di SQL Server e snifing dei parametri

Query Optimizer di SQL Server normalmente crea un piano di query in base ai parametri forniti durante la sua prima esecuzione, quindi riutilizza questo piano per tutte le query future anche se vengono forniti parametri diversi. Questo è noto come parameter sniffing.

Il problema che abbiamo con il nostro database è che SQL Server a volte costruisce questi piani in base a parametri che puntano a un tenant più piccolo, che funziona bene per quel tenant, ma poi quando riapplica il piano memorizzato nella cache a un tenant più grande fallisce catastroficamente (di solito fuori tempo, in effetti). Normalmente scopriamo questa situazione solo quando uno dei nostri inquilini più grandi ci contatta per verificare gli errori di timeout, quindi dobbiamo entrare nel sistema e svuotare manualmente tutti i piani di query per correggerlo.

C'è un suggerimento di query che è possibile utilizzare per impedire che SQL Server memorizzi nella cache i piani di query (OPTIMIZE FOR UNKNOWN) ma ciò comporta un sovraccarico in più poiché il piano di query viene rigenerato ogni volta che viene richiamata la query. Un ulteriore problema è che stiamo utilizzando Entity Framework che non offre alcuna possibilità di specificare l'suggerimento OPTIMIZE FOR UNKNOWN sulle query.

Quindi la domanda è: qual è la prassi migliore per i database multi-tenant in merito allo sniffing dei parametri? C'è un modo per disabilitare il parametro sniffing in tutto il database senza doverlo specificare su ogni query? Se è così, è anche l'approccio migliore? Devo dividere i dati in qualche altro modo? C'è qualche altro approccio a cui non sto pensando?

+0

AFAIK, è necessario utilizzare stored procedure per risolvere questo problema. A meno che non ci siano alcune funzionalità di EF che possono aiutarti. – RBarryYoung

+0

'OPTIMIZE FOR UNKNOWN' non ha il comportamento che descrivi. Lo stai confondendo con 'OPTION (RECOMPILE)'. Se sei su Enterprise Edition puoi consultare le guide di piano per fornire il suggerimento. Oppure c'è un flag di traccia (4136) per [disabilitare completamente il parametro sniffing] (http://support.microsoft.com/kb/980653) ma che si applica al ** istanza ** non al database. –

risposta

3

ho avuto problemi simili, e hanno risolto con successo passando i miei parametri in questo modo:

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] 

in altre parole, la creazione di una variabile locale su base 1-1 per ciascun parametro passato in e quindi solo facendo riferimento a quelle nuove variabili all'interno della logica dell'SP. Probabilmente mi sto perdendo qualche ottimizzazione che SQL Server potrebbe fare per me, ma soprattutto mi manca la prestazione davvero orribile che ricevo quando interviene il param eter sniffing.

Nel tuo caso, forse potresti provare a fare questo solo per l'ID multi-tenant (che presumo sia un parametro per tutti gli SP?) e consentire al server SQL di ottimizzare il resto dei parametri, se possibile.

+0

Questo è essenzialmente ciò che l'hint di query OPTIMIZE FOR UNKNOWN fa. Sfortunatamente non posso utilizzare entrambi gli approcci con Entity Framework perché non posso modificare la query che viene generata. – Mike

Problemi correlati