Introduzione
Tra il 1998 e l'inizio del 2014, SQL Server ha utilizzato uno stimatore di cardinalità (CE), ma avrebbe introdotto un nuovo livello di compatibilità del database con ogni nuova versione principale di SQL Server (ad eccezione di SQL Server 2008 R2). I livelli di compatibilità nativi per SQL Server sono mostrati dalla versione principale di SQL Server nella Tabella 1:
Versione SQL Server | Livello di compatibilità nativo |
---|---|
SQL Server 7.0 | 70 |
SQL Server 2000 | 80 |
SQL Server 2005 | 90 |
SQL Server 2008 SQL Server 2008 R2 | 100 |
SQL Server 2012 | 110 |
SQL Server 2014 | 120 |
SQL Server 2016 | 130 |
SQL Server 2017 | 140 |
SQL Server 2019 | 150 |
Tabella 1:versioni di SQL Server e livelli di compatibilità nativi
Tra SQL Server 7.0 e SQL Server 2012 non esisteva alcuna connessione tra il livello di compatibilità di un database e lo stimatore di cardinalità che le query in quel database avrebbero usato. Questo perché esisteva un solo stimatore di cardinalità, che ha ricevuto un importante aggiornamento nel 1998. Il livello di compatibilità di un database è stato utilizzato solo per la compatibilità funzionale con le versioni precedenti e per abilitare/disabilitare alcune nuove funzionalità in ogni nuova versione di SQL Server (vedi questo Stack Exchange risposta per esempi di come il comportamento è cambiato tra 80 e 90, probabilmente il cambiamento più dirompente). A differenza della versione file di un database SQL Server, puoi modificare il livello di compatibilità di un database in qualsiasi momento, a qualsiasi livello di compatibilità supportato, con un semplice comando ALTER DATABASE.
Per impostazione predefinita, se hai creato un nuovo database in SQL Server 2012, il livello di compatibilità sarebbe impostato su 110, ma è possibile modificarlo a un livello precedente se lo si desidera. Se hai ripristinato un backup del database da un'istanza di SQL Server 2008 a un'istanza di SQL Server 2012, aggiornerebbe la versione del file del database, ma lascerebbe il livello di compatibilità dove si trovava nell'istanza di SQL Server 2008 (a meno che non fosse 80, il che ottenere l'aggiornamento a 90, la versione minima supportata da SQL Server 2012). Oltre a conoscere la differenza fondamentale tra la versione del file di un database e il livello di compatibilità di un database, la maggior parte dei DBA e degli sviluppatori non doveva preoccuparsi molto dei livelli di compatibilità del database prima del rilascio di SQL Server 2014. In molti casi, i livelli di compatibilità della maggior parte dei database non sono mai stati modificati dopo la migrazione a una nuova versione di SQL Server. Questo di solito non causava alcun problema a meno che tu non avessi effettivamente bisogno di una nuova funzionalità o comportamento che fosse cambiato nell'ultimo livello di compatibilità del database.
Modifiche a SQL Server 2014
Questo vecchio stato di cose è cambiato radicalmente con il rilascio di SQL Server 2014. SQL Server 2014 ha introdotto un "nuovo" stimatore di cardinalità abilitato per impostazione predefinita quando un database era nel livello di compatibilità 120. Nel classico whitepaper "Ottimizzazione dei piani di query con lo strumento per la stima della cardinalità di SQL Server 2014", Joe Sack spiega il background e il comportamento di questa modifica nell'aprile del 2014. In molti casi, la maggior parte delle query è stata eseguita più velocemente quando si utilizzava la nuova cardinalità stimatore, ma era abbastanza comune imbattersi in alcune query che presentavano importanti regressioni delle prestazioni con il nuovo stimatore di cardinalità. In tal caso, SQL Server 2014 non disponeva di molte opzioni per alleviare i problemi di prestazioni causati dal nuovo CE. Il whitepaper di Joe copre queste opzioni in modo molto dettagliato, ma essenzialmente eri limitato a flag di traccia a livello di istanza o suggerimenti di query a livello di query per controllare quale stimatore di cardinalità è stato utilizzato da Query Optimizer, a meno che tu non volessi ripristinare il livello di compatibilità 110 o inferiore .
Modifiche a SQL Server 2016
SQL Server 2016 ha introdotto opzioni di configurazione con ambito database, che offrono la possibilità di controllare alcuni comportamenti precedentemente configurati a livello di istanza, usando un comando ALTER DATABASE SCOPED CONFIGURATION. In SQL Server 2016, queste opzioni includevano MAXDOP, LEGACY_CARDINALITY STIMATION, PARAMETER_SNIFFING e QUERY_OPTIMIZER_HOTFIXES. C'era anche un'opzione CLEAR PROCEDURE_CACHE che ti permetteva di svuotare l'intera cache del piano per un singolo database.
Le più rilevanti in questo contesto sono le opzioni di configurazione con ambito database LEGACY_CARDINALITY ESTIMATION e QUERY_OPTIMIZER_HOTFIXES. LEGACY_CARDINALITY STIMATION abilita il CE legacy indipendentemente dall'impostazione del livello di compatibilità del database. Equivale al flag di traccia 9481, ma interessa solo il database in questione, non l'intera istanza. Ti consente di impostare il livello di compatibilità del database su 130 per ottenere una serie di vantaggi funzionali e prestazionali, ma utilizza comunque il database CE legacy a livello di database (a meno che non venga sovrascritto da un suggerimento per la query a livello di query).
L'opzione QUERY_OPTIMIZER_HOTFIXES equivale al flag di traccia 4199 a livello di database. SQL Server 2016 abiliterà tutti gli hotfix di Query Optimizer prima SQL Server 2016 RTM quando si usa il livello di compatibilità del database 130 (senza abilitare il flag di traccia 4199). Se abiliti TF 4199 o abiliti QUERY_OPTIMIZER_HOTFIXES, riceverai anche tutti gli hotfix di Query Optimizer che sono stati rilasciati dopo SQL Server 2016 RTM.
SQL Server 2016 SP1 ha anche introdotto i suggerimenti per le query USE HINT che sono più facili da usare, comprendere e ricordare rispetto ai precedenti suggerimenti per le query QUERYTRACEON. Ciò offre un controllo ancora più dettagliato sul comportamento dell'ottimizzatore correlato al livello di compatibilità del database e alla versione dello stimatore di cardinalità utilizzato. È possibile eseguire una query su sys.dm_exec_valid_use_hints per ottenere un elenco di nomi USE HINT validi per la build esatta di SQL Server in esecuzione.
Modifiche a SQL Server 2017
La nuova funzionalità di elaborazione delle query adattiva è stata aggiunta in SQL Server 2017 ed è abilitata per impostazione predefinita quando si utilizza il livello di compatibilità del database 140.
Microsoft sta cercando di allontanarsi dalla vecchia terminologia di "New CE" e "Old CE", poiché in ogni nuova versione principale di SQL Server sono presenti modifiche e correzioni all'ottimizzazione delle query. Per questo motivo, non esiste più un unico "Nuovo CE". Invece, Microsoft vuole fare riferimento a CE70 (CE predefinito per SQL Server 7.0 tramite SQL Server 2012), CE120 per SQL Server 2014, CE130 per SQL Server 2016, CE140 per SQL Server 2017 e CE150 per SQL Server 2019. A partire da SQL Server 2017 CU10, è possibile utilizzare la funzionalità USE HINT per controllarlo con suggerimenti per le query. Ad esempio:
/*...query...*/ OPTION (USE HINT('QUERY_OPTIMIZER_COMPATIBILITY_LEVEL_130'));
… sarebbe un valido suggerimento per la query per forzare lo stimatore di cardinalità CE130 per una particolare query.
Modifiche a SQL Server 2019
SQL Server 2019 aggiunge ancora più miglioramenti delle prestazioni e modifiche del comportamento abilitate per impostazione predefinita quando un database usa la modalità di compatibilità 150. Un ottimo esempio è l'integrazione UDF scalare. Un altro esempio è la funzionalità di elaborazione delle query intelligente, che è un superset dell'elaborazione adattiva delle query in SQL Server 2017.
Sono disponibili cinque nuove opzioni USE HINT, inclusi i modi per disabilitare la modalità batch o disabilitare il feedback di concessione della memoria adattiva, come mostrato nella Tabella 2:
DISABLE_BATCH_MODE_ADAPTIVE_JOINS |
DISABLE_BATCH_MODE_MEMORY_GRANT_FEEDBACK |
DISABLE_INTERLEAVED_EXECUTION_TVF |
DISALLOW_BATCH_MODE |
QUERY_OPTIMIZER_COMPATIBILITY_LEVEL_150 |
Tabella 2:Nuove opzioni USE SUGGERIMENTI
E ci sono anche sedici nuove opzioni di configurazione con ambito database (a partire da CTP 2.2) che offrono il controllo a livello di database di più elementi che sono anche interessati dai flag di traccia o dal livello di compatibilità del database. Offre un controllo più dettagliato delle modifiche di livello superiore abilitate per impostazione predefinita con il livello di compatibilità del database 150. Queste sono elencate nella Tabella 3:
ACCELERATED_PLAN_FORCING | ELEVATE_RESUMABLE | ROW_MODE_MEMORY_GRANT_FEEDBACK |
BATCH_MODE_ADAPTIVE_JOINS | GLOBAL_TEMPORARY_TABLE_AUTO_DROP | TSQL_SCALAR_UDF_INLINEING |
BATCH_MODE_MEMORY_GRANT_FEEDBACK | INTERLEAVED_EXECUTION_TVF | XTP_PROCEDURE_EXECUTION_STATISTICS |
BATCH_MODE_ON_ROWSTORE | ISOLATE_SECURITY_POLICY_CARDINALITY | XTP_QUERY_EXECUTION_STATISTICS |
DEFERRED_COMPILATION_TV | LIGHTWEIGHT_QUERY_PROFILING | |
ELEVATE_ONLINE | OPTIMIZE_FOR_AD_HOC_WORKLOADS |
Tabella 3:Nuove opzioni di configurazione con ambito database
Conclusione
La migrazione a una versione moderna di SQL Server (ovvero SQL Server 2016 o versioni successive) è notevolmente più complicata rispetto alle versioni legacy di SQL Server. A causa delle modifiche associate ai vari livelli di compatibilità del database e alle varie versioni dello stimatore di cardinalità, in realtà è molto importante riflettere, pianificare e testare effettivamente il livello di compatibilità del database che si desidera utilizzare nella nuova versione di SQL Server stanno migrando i database esistenti in.
Il processo di aggiornamento consigliato da Microsoft prevede l'aggiornamento all'ultima versione di SQL Server, mantenendo il livello di compatibilità del database di origine. Quindi, abilita Query Store su ogni database e raccogli i dati di base sul carico di lavoro. Successivamente, imposti il livello di compatibilità del database sulla versione più recente, quindi utilizza Query Store per correggere le regressioni delle prestazioni forzando l'ultimo piano valido noto.
Vuoi davvero evitare una migrazione "cieca" casuale in cui sei beatamente inconsapevole di come funziona e di come reagirà il tuo carico di lavoro a questi cambiamenti. La modifica del livello di compatibilità del database in una versione appropriata e l'utilizzo delle opzioni di configurazione con ambito database appropriate, insieme ai suggerimenti per le query appropriati ove assolutamente necessario, è estremamente importante con le versioni moderne di SQL Server.