Database
 sql >> Database >  >> RDS >> Database

Piani diversi per server identici

Nel mio ultimo post, "Più piani per una query 'identica'", ho parlato del caso in cui stai ricevendo due piani diversi per quella che ritieni sia la stessa query, così come del caso in cui stai ricevendo due copie del uguale piano (e potrebbe anche non saperlo). Come abbiamo esaminato lì, "identico" può essere una parola piuttosto forte.

Un altro scenario che mette in crisi le persone è il caso in cui ripristinano un database su un server diverso, ad esempio ripristinano un database di produzione su un server di test "identico" e ottengono caratteristiche di prestazioni diverse o piani diversi per la stessa query (no virgolette questa volta – sto davvero parlando di query veramente identiche).

I server sono veramente "identici"?

Questi ragazzi possono sembrare simili, ma non sono del tutto identici.

Se ti imbatti in questo scenario, la prima cosa che devi chiederti è se questi due server sono davvero identici. Alcune cose da controllare:

  • Versione – Molte modifiche al comportamento dell'ottimizzatore e delle query vengono inviate tramite service pack e aggiornamenti cumulativi. Spesso ho visto persone dire:"Beh, sono entrambi del 2008!" – quando, in effetti, uno era il 2008 e l'altro era il 2008 R2, oppure erano a service pack diversi o addirittura a livelli di aggiornamento cumulativo. Poiché molte persone che leggono @@VERSION confondono le informazioni sul service pack del sistema operativo per le informazioni sul service pack di SQL Server, direi che è meglio:

    SELECT SERVERPROPERTY (N'ProductVersion' );

    Non posso sottolineare abbastanza l'importanza di utilizzare la stessa identica versione per eseguire veri test da mela a mela. Se utilizzi SQL Server 2012 o versioni successive, puoi controllare i nostri post di build (SQL Server 2012 | SQL Server 2014) per determinare il service pack o l'aggiornamento cumulativo necessario per assicurarti che le versioni corrispondano.

  • Edizione – Anche se si spera che tu stia utilizzando la stessa edizione su entrambi i server (o equivalenti, poiché a parte le licenze, Developer e Evaluation sono gli stessi di Enterprise), le discrepanze qui possono portare a comportamenti molto diversi. Ad esempio, edizioni diverse hanno capacità di calcolo diverse per varie funzionalità e poi ci sono aspetti più sottili come la possibilità di utilizzare una vista indicizzata senza l'hint NOEXPAND o di eseguire modifiche allo schema o manutenzione dell'indice online. Puoi confrontare le edizioni utilizzando:

    SELECT SERVERPROPERTY (N'Edition' );

  • Conteggio CPU – SQL Server utilizza sicuramente il numero di scheduler disponibili durante il processo di produzione di un piano di esecuzione e non si può negare che il numero di core può influire sulle prestazioni effettive di runtime (tralasciamo la velocità di clock, poiché raramente è un fattore significativo nella query prestazione). Non solo convalidare il numero di core installati fisicamente nel server sottostante, ma controllare anche il log degli errori di SQL Server per il numero di CPU che SQL Server può effettivamente utilizzare a causa delle licenze. Anche dimenticando il conteggio dei core grezzi, su un sistema NUMA, le restrizioni artificiali qui possono portare a profili di prestazioni molto diversi. Per ulteriori informazioni, vedere il recente post di Brent Ozar, "Perché le licenze basate su core sono importanti per l'ottimizzazione delle prestazioni". L'edizione si collega anche qui, poiché in SQL Server 2012 e 2014, l'edizione standard può utilizzare solo 16 core, indipendentemente dalle impostazioni o dall'hardware fisico che potrebbero farti credere. Altre impostazioni che possono influenzare in modo diverso la scelta del piano basato sulla CPU e le prestazioni includono Resource Governor, MAXDOP a livello di server, affinità CPU e soglia di costo per il parallelismo.
  • Quantità di memoria – Come le CPU, l'ottimizzatore effettua scelte di pianificazione in base alla quantità di memoria disponibile. E come le CPU, non sto parlando solo della quantità di RAM installata nel sistema, ma della quantità di memoria concessa a SQL Server e di quanto sta veramente utilizzando. Controlla le impostazioni della memoria massima del server, ma anche i contatori delle prestazioni per la memoria totale e di destinazione e persino DBCC MEMORYSTATUS. Altre cose che potresti voler rivedere includono le impostazioni di Resource Governor e Blocca pagine in memoria. Esiste anche un'impostazione che, se diversa tra due server, può avere un effetto significativo sulla quantità di cache del piano utilizzata per lo stesso insieme di query:ottimizzazione per carichi di lavoro ad hoc. Kimberly Tripp ha un ottimo post su questo:pianificazione della cache e ottimizzazione per carichi di lavoro ad hoc. Infine, se il server è virtuale, tieni presente che l'ambiente può svolgere un ruolo qui, soprattutto quando le impostazioni della memoria della macchina virtuale non corrispondono alla produzione o sono dinamiche.
  • Pool di buffer/cache del piano – Quando ripristini il database sul server di prova, ci sono un sacco di cose che semplicemente non sono pronte per te subito. Il pool di buffer non contiene nessuno dei dati che potrebbero essere esistiti nel server di origine, quindi sarà necessario un I/O aggiuntivo per caricare i dati in memoria la prima volta che viene eseguita la query. E se il pool di buffer è limitato in modo diverso dalla produzione a causa di alcuni dei fattori precedenti, potrebbe non essere possibile ottenere gli stessi modelli di prestazioni anche dopo aver eseguito la query più volte – Paul White (@SQL_Kiwi) ne parla nella sua risposta su Amministratori di database. Inoltre, la cache del piano non conterrà nessuno dei piani esistenti in produzione, quindi almeno, anche se lo stesso piano alla fine viene compilato (cosa che potrebbe non verificarsi a causa di parametri diversi rispetto a quando il piano è stato compilato sull'originale server) – avrai costi di compilazione aggiuntivi. E quelli possono cambiare se hai anche dei flag di traccia che influiscono sul piano.
  • Sottosistema disco – Sebbene la velocità e la dimensione dei dischi utilizzati non influiscano direttamente sulla scelta del piano, possono certamente influenzare le prestazioni osservate, il che può farti chiedere perché la stessa query, con lo stesso piano, viene eseguita molto più velocemente su una sistema rispetto all'altro. L'I/O è in genere il collo di bottiglia più grande di SQL Server ed è piuttosto raro che un server di test abbia davvero lo stesso sottosistema sottostante del suo equivalente di produzione. Quindi, se noti differenze di prestazioni tra i due sistemi e i piani e altri elementi hardware sono gli stessi, questo potrebbe essere il prossimo posto migliore da controllare. E non dimenticare che, a partire da SQL Server 2014, Resource Governor potrebbe imporre vincoli alle prestazioni di I/O.
  • Traccia i flag – Controllare l'elenco dei flag di traccia globale impostati su entrambi i server; ce ne sono molti che possono influenzare l'ottimizzazione, il comportamento del piano e le prestazioni percepite, anche se tutte le impostazioni di cui sopra sono identiche. Ecco 10 comuni e notevoli (sebbene questo non sia assolutamente un'approvazione per attivare nessuno di questi senza un test di regressione approfondito):

    Flag Spiegazione
    2301 Costringe l'ottimizzatore a dedicare più tempo alla ricerca di un piano ottimale.
    2312 Forza il nuovo stimatore di cardinalità di SQL Server 2014.
    2335 Provoca concessioni di memoria più conservative.
    2453 Forza OPZIONE (RICIMPILA) per query che fanno riferimento a variabili di tabella.
    2861 Consente a SQL Server di memorizzare nella cache piani banali/a costo zero.
    4136 In effetti, aggiunge OTTIMIZZA PER SCONOSCIUTO a tutte le query (per contrastare lo sniffing dei parametri).
    4199 Un ombrello contenente tutta una serie di correzioni di ottimizzatore.
    8744 Disabilita il pre-lettura per i loop nidificati.
    9481 Disattiva il nuovo stimatore di cardinalità di SQL Server 2014.


    L'elenco dei flag di traccia non è affatto esaustivo; ce ne sono molti altri, compresi quelli privi di documenti che mi è stato chiesto di non menzionare. Se stai usando altri non elencati sopra (e non puoi spiegare perché), potresti trovare indizi in KB #920093, KB #2964518, Trace Flags (MSDN) o Trace Flags in SQL Server (TechNet). Troverai anche alcune preziose informazioni in vari post di Paul White, qui o su sql.kiwi.

  • Concorrenza – Presumibilmente il sistema di test viene utilizzato per cose diverse da quelle che stai attualmente testando. E a meno che tu non stia eseguendo un replay di qualche tipo, probabilmente ha anche un profilo del carico di lavoro molto diverso. Queste differenze nel carico di lavoro possono ovviamente avere un impatto diretto sulla disponibilità di risorse per soddisfare le richieste che stai testando e, a loro volta, sulle prestazioni percepite di tali richieste. Non dimenticare di verificare la presenza di altri servizi che potrebbero non esistere in produzione o esistere ma vengono utilizzati in modi diversi (come Analysis Services, Reporting Services, servizi Windows e persino le tue applicazioni). Al contrario, potrebbero esserci servizi come questo in produzione che influiscono sulle prestazioni lì o un sovraccarico aggiuntivo sull'istanza stessa che non viene imitato nel test:a parte il carico di lavoro di produzione effettivo, pensa a cose come traccia, eventi estesi, monitoraggio ad alto impatto, rilevamento delle modifiche, acquisizione dei dati delle modifiche, controllo, broker di servizi, manutenzione dell'indice, processi di backup, controlli DBCC, mirroring, replica, gruppi di disponibilità e l'elenco potrebbe continuare all'infinito...

I database sono ancora "identici"?

Supponendo che tutte le variabili hardware e del carico di lavoro corrispondano abbastanza bene, può essere comunque difficile garantire che i database rimangano gli stessi. Se si esegue un backup/ripristino sul sistema di test, il nuovo database inizia come identico all'origine (ad eccezione della posizione fisica e della sicurezza). Ma non appena inizi a toccarlo in qualsiasi modo, si discosta molto rapidamente dalla copia di produzione, poiché potresti eseguire una o tutte le seguenti operazioni:

  • Modifica dati, schema o entrambi.
  • Avvia inavvertitamente un aggiornamento automatico delle statistiche.
  • Aggiungi, deframmenta o ricostruisci manualmente gli indici oppure crea o aggiorna le statistiche.
  • Modifica le impostazioni del database come il livello di compatibilità, il livello di isolamento, la parametrizzazione forzata, gli indici XML selettivi o qualsiasi opzione denominata "Auto"-. (Diamine, anche le posizioni dei file di registro e di dati e le impostazioni di crescita possono influire sulle prestazioni delle query, incluso tempdb.)
  • Svuota la cache del piano, il pool di buffer o entrambi, direttamente o come effetto collaterale di altri eventi (come una RICONFIGURA o un riavvio del servizio).

Inoltre, una volta che inizi a generare nuovi piani di query, anche prima che avvenga una qualsiasi delle modifiche precedenti, devi ricordare che potrebbero essere basati su dati diversi dai dati utilizzati per generare piani per le stesse query in produzione. Ad esempio, la cardinalità quando il piano è stato compilato in produzione potrebbe essere stata notevolmente distorta tra quel momento e il momento del backup, il che significa che il nuovo piano verrà generato in base a statistiche e informazioni sull'istogramma diverse.

Queste cose divergono ulteriormente se non si tratta, in effetti, di un ripristino recente, ma piuttosto di due schemi e set di dati che mantieni sincronizzati in altri modi (come le distribuzioni manuali di schemi e/o modifiche ai dati o persino la replica). A causa dei limiti di spazio su disco, potresti anche aver preso solo un sottoinsieme di dati di produzione, o anche un clone di sole statistiche:queste differenze nei dati porteranno quasi sicuramente a caratteristiche di prestazioni diverse per tutte le query tranne che per la più semplice, anche se lo fai fortuna e ottieni gli stessi piani per alcuni.

Le query sono davvero "identiche"?

Anche se tutto quanto sopra viene verificato, ci sono ancora scenari in cui stai ottenendo un piano diverso a causa delle impostazioni della sessione (potresti utilizzare una copia diversa di SSMS, con impostazioni diverse o uno strumento client completamente diverso) o schemi predefiniti diversi ( potresti connetterti al server di prova come un accesso di autenticazione Windows o SQL diverso, ad esempio). Ho parlato molto di queste cose nel mio post precedente.

Conclusione

Sebbene ci siano modi per mitigare alcune differenze (controlla DBCC OPTIMIZER_WHATIF per ingannare il tuo server di test facendogli credere cose fenomenali sull'hardware sottostante), la verità è che sarà molto difficile fare in modo che due server funzionino in modo affidabile e coerentemente identico e che ci sono potenzialmente dozzine di motivi per cui potresti ottenere piani diversi o prestazioni diverse su due server simili (o addirittura identici).

Hai qualche trucco particolare? Hai dei punti dolenti lancinanti con le idee di cui sopra (o altre che ho trascurato di menzionare)? Per favore condividi i commenti qui sotto!