Introdução
Entre 1998 e o início de 2014, o SQL Server usou um estimador de cardinalidade (CE), mas introduziria um novo nível de compatibilidade de banco de dados com cada nova versão principal do SQL Server (com exceção do SQL Server 2008 R2). Os níveis de compatibilidade nativa do SQL Server são mostrados pela versão principal do SQL Server na Tabela 1:
Versão do SQL Server | Nível de compatibilidade nativa |
---|---|
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 |
Tabela 1:versões do SQL Server e níveis de compatibilidade nativa
Entre o SQL Server 7.0 e o SQL Server 2012, não havia conexão entre o nível de compatibilidade de um banco de dados e o estimador de cardinalidade que as consultas nesse banco de dados usariam. Isso ocorre porque havia apenas um estimador de cardinalidade, que recebeu uma grande atualização em 1998. O nível de compatibilidade de um banco de dados era usado apenas para compatibilidade funcional com versões anteriores e para habilitar/desabilitar alguns novos recursos em cada nova versão do SQL Server (veja este Resposta do Stack Exchange para exemplos de como o comportamento mudou entre 80 e 90, provavelmente a mudança mais disruptiva). Ao contrário da versão de arquivo de um banco de dados SQL Server, você pode alterar o nível de compatibilidade de um banco de dados a qualquer momento, para qualquer nível de compatibilidade com suporte, com um simples comando ALTER DATABASE.
Por padrão, se você criou um novo banco de dados no SQL Server 2012, o nível de compatibilidade seria definido como 110, mas você poderia alterá-lo para um nível anterior, se desejar. Se você restaurou um backup de banco de dados de uma instância do SQL Server 2008 para uma instância do SQL Server 2012, ele atualizaria a versão do arquivo do banco de dados, mas deixaria o nível de compatibilidade em que estava na instância do SQL Server 2008 (a menos que fosse 80, o que seja atualizado para 90, a versão mínima suportada pelo SQL Server 2012). Além de conhecer a diferença fundamental entre a versão do arquivo de um banco de dados e o nível de compatibilidade de um banco de dados, a maioria dos DBAs e desenvolvedores não precisava se preocupar muito com os níveis de compatibilidade do banco de dados antes do lançamento do SQL Server 2014. Em muitos casos, a maioria dos bancos de dados nunca teve seus níveis de compatibilidade alterados após uma migração para uma nova versão do SQL Server. Isso geralmente não causava problemas, a menos que você realmente precisasse de um novo recurso ou comportamento alterado no nível de compatibilidade de banco de dados mais recente.
Mudanças do SQL Server 2014
Esse antigo estado de coisas mudou radicalmente com o lançamento do SQL Server 2014. O SQL Server 2014 introduziu um “novo” estimador de cardinalidade que foi habilitado por padrão quando um banco de dados estava no nível de compatibilidade 120. No whitepaper clássico, “Otimizando seus planos de consulta com o estimador de cardinalidade do SQL Server 2014”, Joe Sack explica o histórico e o comportamento dessa alteração em abril de 2014. Em muitos casos, a maioria de suas consultas foi executada mais rapidamente ao usar a nova cardinalidade estimador, mas era bastante comum encontrar algumas consultas que apresentavam grandes regressões de desempenho com o novo estimador de cardinalidade. Se isso acontecesse, o SQL Server 2014 não tinha tantas opções para aliviar os problemas de desempenho causados pelo novo CE. O whitepaper de Joe aborda essas opções em detalhes, mas, essencialmente, você estava limitado a sinalizadores de rastreamento em nível de instância ou dicas de consulta em nível de consulta para controlar qual estimador de cardinalidade foi usado pelo otimizador de consulta, a menos que você quisesse reverter para o nível de compatibilidade 110 ou inferior .
Mudanças do SQL Server 2016
O SQL Server 2016 introduziu opções de configuração no escopo do banco de dados, que permitem controlar alguns comportamentos anteriormente configurados no nível da instância, usando um comando ALTER DATABASE SCOPED CONFIGURATION. No SQL Server 2016, essas opções incluíam MAXDOP, LEGACY_CARDINALITY ESTIMATION, PARAMETER_SNIFFING e QUERY_OPTIMIZER_HOTFIXES. Também havia uma opção CLEAR PROCEDURE_CACHE que permitia limpar todo o cache do plano para um único banco de dados.
As mais relevantes neste contexto são as opções de configuração com escopo de banco de dados LEGACY_CARDINALITY ESTIMATION e QUERY_OPTIMIZER_HOTFIXES. LEGACY_CARDINALITY ESTIMATION habilita o CE legado independentemente da configuração do nível de compatibilidade do banco de dados. É equivalente ao sinalizador de rastreamento 9481, mas afeta apenas o banco de dados em questão, não a instância inteira. Ele permite definir o nível de compatibilidade do banco de dados para 130 para obter vários benefícios funcionais e de desempenho, mas ainda usar o banco de dados CE legado em todo o banco de dados (a menos que substituído por uma dica de consulta no nível de consulta).
A opção QUERY_OPTIMIZER_HOTFIXES é equivalente ao sinalizador de rastreamento 4199 no nível do banco de dados. O SQL Server 2016 habilitará todos os hotfixes do otimizador de consulta antes SQL Server 2016 RTM quando você usa o nível de compatibilidade do banco de dados 130 (sem habilitar o sinalizador de rastreamento 4199). Se você habilitar o TF 4199 ou habilitar QUERY_OPTIMIZER_HOTFIXES, você também receberá todos os hotfixes do otimizador de consulta que foram lançados depois SQL Server 2016 RTM.
O SQL Server 2016 SP1 também introduziu as dicas de consulta USE HINT que são mais fáceis de usar, entender e lembrar do que as dicas de consulta QUERYTRACEON mais antigas. Isso oferece um controle ainda mais refinado sobre o comportamento do otimizador relacionado ao nível de compatibilidade do banco de dados e à versão do estimador de cardinalidade que está sendo usado. Você pode consultar sys.dm_exec_valid_use_hints para obter uma lista de nomes USE HINT válidos para a compilação exata do SQL Server que você está executando.
Mudanças do SQL Server 2017
O novo recurso de processamento de consulta adaptável foi adicionado no SQL Server 2017 e é habilitado por padrão quando você está usando o nível de compatibilidade de banco de dados 140.
A Microsoft está tentando se afastar da terminologia antiga de “Novo CE” e “Antigo CE”, já que na verdade existem mudanças e correções na otimização de consultas em cada nova versão principal do SQL Server. Por causa disso, não existe mais um “Novo CE” único. Em vez disso, a Microsoft quer se referir a CE70 (CE padrão para SQL Server 7.0 a SQL Server 2012), CE120 para SQL Server 2014, CE130 para SQL Server 2016, CE140 para SQL Server 2017 e CE150 para SQL Server 2019. Começando com SQL Server 2017 CU10, você pode usar a funcionalidade USE HINT para controlar isso com dicas de consulta. Por exemplo:
/*...query...*/ OPTION (USE HINT('QUERY_OPTIMIZER_COMPATIBILITY_LEVEL_130'));
… seria uma dica de consulta válida para forçar o estimador de cardinalidade CE130 para uma consulta específica.
Mudanças do SQL Server 2019
O SQL Server 2019 está adicionando ainda mais melhorias de desempenho e alterações de comportamento que são habilitadas por padrão quando um banco de dados está usando o modo de compatibilidade 150. Um excelente exemplo é a inserção de UDF escalar. Outro exemplo é o recurso de processamento de consulta inteligente, que é um superconjunto do processamento de consulta adaptável no SQL Server 2017.
Há cinco novas opções de USE HINT, incluindo maneiras de desabilitar o modo batch ou desabilitar o feedback de concessão de memória adaptável, conforme mostrado na Tabela 2:
DISABLE_BATCH_MODE_ADAPTIVE_JOINS |
DISABLE_BATCH_MODE_MEMORY_GRANT_FEEDBACK |
DISABLE_INTERLEAVED_EXECUTION_TVF |
DISALLOW_BATCH_MODE |
QUERY_OPTIMIZER_COMPATIBILITY_LEVEL_150 |
Tabela 2:Novas opções de USE HINT
E também há dezesseis novas opções de configuração no escopo do banco de dados (a partir do CTP 2.2) que fornecem controle no nível do banco de dados de mais itens que também são afetados por sinalizadores de rastreamento ou nível de compatibilidade do banco de dados. Ele oferece um controle mais refinado das alterações de nível superior que são habilitadas por padrão com o nível de compatibilidade de banco de dados 150. Elas estão listadas na Tabela 3:
ACCELERATED_PLAN_FORCING | ELEVATE_RESUMABLE | ROW_MODE_MEMORY_GRANT_FEEDBACK |
BATCH_MODE_ADAPTIVE_JOINS | GLOBAL_TEMPORARY_TABLE_AUTO_DROP | TSQL_SCALAR_UDF_INLINING |
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 |
Tabela 3:Novas opções de configuração no escopo do banco de dados
Conclusão
Migrar para uma versão moderna do SQL Server (ou seja, SQL Server 2016 ou mais recente) é significativamente mais complicado do que era com versões herdadas do SQL Server. Devido às alterações associadas aos vários níveis de compatibilidade do banco de dados e às várias versões do estimador de cardinalidade, é muito importante pensar, planejar e testar o nível de compatibilidade do banco de dados que você deseja usar na nova versão do SQL Server que você deseja usar. estão migrando seus bancos de dados existentes para.
O processo de atualização recomendado pela Microsoft é atualizar para a versão mais recente do SQL Server, mas manter o nível de compatibilidade do banco de dados de origem. Em seguida, habilite o Repositório de Consultas em cada banco de dados e colete dados de linha de base na carga de trabalho. Em seguida, você define o nível de compatibilidade do banco de dados para a versão mais recente e, em seguida, usa o Repositório de Consultas para corrigir regressões de desempenho forçando o último plano válido conhecido.
Você realmente deseja evitar uma migração “cega” aleatória, na qual você não sabe como isso funciona e como sua carga de trabalho reagirá a essas mudanças. Alterar o nível de compatibilidade do banco de dados para uma versão apropriada e usar as opções de configuração no escopo do banco de dados apropriadas, juntamente com as dicas de consulta apropriadas quando absolutamente necessário, é extremamente importante com as versões modernas do SQL Server.