Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

SQL Server Internals:Planejar Cache Pt. II – Recompilação de Planos


Isso faz parte de uma série de cache do plano interno do SQL Server. Certifique-se de ler a primeira postagem de Kalen sobre este tópico.

O SQL Server existe há mais de 30 anos e trabalho com o SQL Server há quase tanto tempo. Eu vi muitas mudanças ao longo dos anos (e décadas!) e versões deste produto incrível. Nestas postagens, compartilharei com você como vejo alguns dos recursos ou aspectos do SQL Server, às vezes com um pouco de perspectiva histórica

No meu artigo anterior , falei sobre o diagnóstico do SQL Server, incluindo as várias opções que o SQL Server tem para reutilizar um plano de consulta. Examinamos três tipos de planos de consulta:ad hoc, preparado e procedimento. Terminei a discussão com uma olhada em uma reutilização inadequada de um plano, que pode acontecer quando o SQL Server aplica o sniffing de parâmetros nas situações erradas. Se um plano é baseado em um valor inicial que faz com que o otimizador gere um plano apropriado para esse valor e, em seguida, o mesmo plano é usado para um valor diferente, o plano pode não ser mais ideal.

Então, o que podemos fazer quando a detecção de parâmetros é um problema? Podemos forçar o SQL Server a criar um novo plano. Normalmente, chamamos o ato de criar um novo plano de 'recompilação', mas provavelmente deveria ser chamado de 'reotimização'. No entanto, a maioria das pessoas usa o termo ‘recompilar’, então é isso que vou usar aqui.

Se o uso inadequado de sniffing de parâmetros for um problema, uma solução simples é dizer ao SQL Server para criar um novo plano. Para instruções individuais, como planos PREPARED que foram parametrizados automaticamente, podemos adicionar a dica RECOMPILE a uma consulta. Usando FORCED parametrizado (discutido no artigo anterior), esta consulta será parametrizada.

SELECT * FROM dbo.newsales 
WHERE SalesOrderID < @num;


Se quisermos ter certeza de obter um novo plano toda vez que executarmos essa consulta, com valores potencialmente muito diferentes para @num, podemos adicionar a dica RECOMPILE conforme mostrado:

SELECT * FROM dbo.newsales
  WHERE SalesOrderID < @num
OPTION (RECOMPILE);

Para procedimentos armazenados, temos três opções. Primeiro, podemos verificar se a recompilação realmente ajudará no desempenho executando o procedimento com a opção RECOMPILE:

EXEC get_sales_range 66666 WITH RECOMPILE;

Esta opção fará com que um novo plano seja gerado apenas para esta execução. Ele não será salvo e certamente não será reutilizado. O valor usecount mostrado em sp_cacheobjects (descrito na postagem anterior) para o procedimento não aumentará, pois o plano original não está sendo reutilizado.

Segundo, se acharmos que a execução de WITH RECOMPILE ajuda, podemos considerar a recriação do procedimento com a opção RECOMPILE, caso em que ele nunca reutilizará o plano e o procedimento não aparecerá no cache do plano.

DROP PROC IF EXISTS get_sales_range;GO
CREATE PROC get_sales_range
   @num int
WITH RECOMPILE
AS
    SELECT * FROM dbo.newsales
    WHERE SalesOrderID < @num;
GO


Para meu pequeno procedimento simples, usar a opção WITH RECOMPILE para todo o procedimento pode fazer sentido. Mas se o procedimento for mais complexo, pode não fazer sentido recompilar todo o procedimento porque uma instrução está causando problemas. Então, a terceira opção é usar a dica RECOMPILE para uma instrução dentro do procedimento, ficando assim:

DROP PROC IF EXISTS get_sales_range;
GO
CREATE PROC get_sales_range
   @num int
AS
    SELECT * FROM dbo.newsales
    WHERE SalesOrderID < @num
    OPTION (RECOMPILE);
GO


O uso de uma dessas opções RECOMPILE pode forçar o SQL Server a criar um novo plano a seu pedido. Agora, veremos quando o diagnóstico do SQL Server apresenta um novo plano quando você não o solicita, ou seja, quando ocorre a recompilação automática de um plano existente?


A recompilação automática de um plano ocorre em dois tipos de situações:

  • Primeiro, se o otimizador determinar que o plano existente não está mais correto, geralmente devido a uma alteração nas definições do objeto, ele precisará criar um novo plano. Por exemplo, se você tiver um plano para uma consulta selecionada na Tabela A e, em seguida, descartar várias colunas ou alterar os tipos de dados das colunas na Tabela A, o SQL Server recompilará a consulta para criar um plano que reflita as alterações de DDL.
  • A segunda situação em que ocorre a recompilação automática é quando o SQL Server determina que o plano pode não ser mais ideal devido a uma alteração nas estatísticas. Na maioria dos casos, se as estatísticas em qualquer uma das colunas ou índices tiverem sido atualizadas desde a última vez que o plano foi compilado, elas serão recompiladas. Mas isso leva a outra questão. Quando as estatísticas são atualizadas? As estatísticas podem ser atualizadas automaticamente quando linhas suficientes nas colunas relevantes forem alteradas. Quantos são suficientes? Falamos sobre isso daqui a pouco.

Por padrão, o SQL Server atualizará as estatísticas automaticamente devido a uma opção de banco de dados que está ATIVA por padrão. Mas se você for um proprietário de banco de dados (ou um SQL 'sa', que aparece como proprietário em todos os bancos de dados), você pode alterar as opções. Uma das opções é chamada AUTO_UPDATE_STATISTICS e outra é chamada AUTO_UPDATE_STATISTICS_ASYNC. A opção AUTO_UPDATE_STATISTICS está ON no banco de dados tempdb, portanto, cada novo banco de dados herda essa opção. Quando esta opção estiver ATIVADA e o mecanismo de execução de consulta detectar alterações em um número suficiente de linhas enquanto uma consulta estiver sendo processada, a execução será pausada enquanto as estatísticas são atualizadas e, em seguida, a consulta é recompilada. A outra opção, AUTO_UPDATE_STATISTICS_ASYNC, pode ter menos efeito no tempo de execução da consulta porque a execução não é pausada, ao custo de usar um possível plano abaixo do ideal. Com a segunda opção, se o mecanismo de execução detectar a necessidade de atualizar as estatísticas, um thread em segundo plano é acionado para fazer a atualização e o thread principal continua executando a consulta com as estatísticas originais e o plano original. A próxima consulta que acessar as tabelas afetadas e ver as estatísticas atualizadas irá recompilar a consulta, mas não irá pausar e fazer a atualização das estatísticas no meio da execução.

Existem mais algumas situações, bem como algumas dicas de consulta que controlam se os planos são recompilados ou não, então mostrarei um fluxograma que compartilharei com você um fluxograma que criei para minhas aulas de treinamento em SQL Server internos.



A seta é onde o SQL Server começa a processar seu lote. Ele primeiro verifica se já existe um plano para seu lote em cache e, se a resposta for NÃO, segue a seta para a direita e compila um plano. O plano é colocado em cache e, em seguida, o SQL Server é iniciado novamente. Sim, o plano deve estar em cache desta vez, então ele segue a seta para baixo e pergunta se uma dica chamada KEEP PLAN foi usada. Se SIM, o SQL Server começa a executar o plano imediatamente e não faz mais verificações.

A próxima pergunta é se alguma alteração DDL foi feita. Se não, ele pergunta sobre várias outras situações sobre as quais não poderei falar neste artigo. Na verdade, eu realmente não vou passar por todas as opções aqui. Vou deixar isso para você. Mas se você tiver alguma dúvida ou confusão, sinta-se à vontade para perguntar na seção de comentários aqui ou me tweet em @sqlqueen. Vou apontar a pergunta na extrema direita:AUTO_STATS_ASYNC ON? Aqui, você pode ver que se a resposta for SIM, existem duas ações. Uma ramificação apenas inicia a execução com o plano existente e a outra é a thread em segundo plano que atualiza as estatísticas, mas não faz mais nada. A próxima consulta encontrará a caixa de decisão no meio “Há novas estatísticas disponíveis” e deve responder SIM, para que a consulta seja recompilada.

A única outra coisa sobre a qual falarei é a pergunta “Alguma estatística está obsoleta?” Isso basicamente significa que as estatísticas estão desatualizadas porque muitas alterações foram feitas. Então agora podemos falar sobre quantos é demais.

Embora existam valores diferentes usados ​​para tabelas muito pequenas, para qualquer tabela com mais de 500 linhas, antes do SQL Server 2016, as estatísticas seriam consideradas 'obsoletas' quando o número de alterações na coluna na qual as estatísticas se basearam excedesse 20 % do número de linhas na tabela. Portanto, para uma tabela de 1.000 linhas, isso pode significar 200 inserções, 200 atualizações ou 200 exclusões. Podem ser alterações de 200 linhas ou 5 linhas atualizadas 40 vezes cada. O SQL Server ainda nos dá uma função que informa quantas alterações foram feitas. Você precisará procurar o número stats_id para as estatísticas em que está interessado, que seria o index_id se as estatísticas pertencerem a um índice. O stats_id pode ser encontrado na visualização chamada sys.stats. Na minha tabela newsales, uso essa consulta para descobrir que o stats_id do índice na coluna SubTotal é 3.

SELECT name, stats_id FROM sys.stats
WHERE object_id = object_id('newsales');


Então eu posso usar esse valor para ver o número de alterações. Deixe-me atualizar algumas linhas primeiro:

UPDATE newsales
SET SubTotal = SubTotal * 0.9
WHERE SalesOrderID < 45200
(1.541 linhas afetadas)

SELECT * FROM sys.dm_db_stats_properties(object_id('newsales'), 3);  



Na verdade, 20% é um número GRANDE. E para muitas tabelas, as consultas podem se beneficiar de estatísticas atualizadas com muito menos de 20% das linhas atualizadas. A partir do 2008R2 SP1, o SQL Server incluiu um Traceflag que você pode usar para alterar o número de linhas para uma escala móvel, conforme mostrado no gráfico a seguir:



A partir do SQL Server 2016, esse novo algoritmo com escala móvel é usado por padrão, desde que você esteja no nível de compatibilidade 130 ou superior.

A maioria das recompilações automáticas de planos de consulta ocorre devido a alterações nas estatísticas. Mas, como mencionei acima, essa não é a única razão para uma recompilação. Mas como é o mais comum, pode ser muito útil estar ciente de quando e como as estatísticas são atualizadas e certificar-se de que as estatísticas em suas tabelas críticas sejam atualizadas com frequência suficiente para garantir que você obtenha os melhores planos!

Analise os dados de desempenho automaticamente para realizar diagnósticos do SQL Server para resolver problemas rapidamente e identificar os servidores onde a degradação do desempenho se origina. Comece a usar o Spotlight Cloud hoje: