Um dos desafios mais difíceis no SQL Server é solucionar problemas com sensibilidade de parâmetro ou estimativa de cardinalidade que causam degradação de desempenho de uma carga de trabalho. Geralmente, você precisará ter o plano de execução real da instrução em execução para poder determinar a causa da degradação do desempenho. No SQL Server 2012, o evento estendido query_post_execution_showplan fornece a capacidade de capturar o plano de execução real para instruções. No entanto, por mais útil que pareça, esse evento não é algo que possa ser usado sem um impacto significativo no desempenho da carga de trabalho em execução no servidor.
Em meu artigo Medindo a “sobrecarga do observador” do SQL Trace vs. Extended Events, mostrei uma comparação do impacto no desempenho do SQL Trace com uma configuração idêntica usando Extended Events no SQL Server 2012. Na época, fiz o teste para esse artigo originalmente Também fiz muitos testes do evento query_post_execution_showplan no SQL Server 2012. Esse evento foi introduzido pela primeira vez no SQL Server 2012 CTP1 quando muitos dos eventos de rastreamento foram transferidos para eventos estendidos para fornecer paridade com o SQL Trace. Naquela época o evento tinha apenas um subconjunto das colunas que foram incluídas no RTM final do SQL Server 2012.
Durante o CTP1 enviei um item Connect solicitando que uma ação fosse criada para permitir a coleta do plano de execução real com eventos no SQL Server 2012. O objetivo era poder usar os eventos module_end ou sql_statement_completed para identificar quando a execução de um procedimento ou declaração excede sua duração normal. Por exemplo, no cenário de sensibilidade de parâmetro, onde um plano menos ideal é gerado para os valores normais de parâmetro, o evento pode ser usado para coletar o plano de execução real dessa instrução por meio de uma ação. Em resposta, a equipe do SQL Server adicionou as colunas duration e cpu_time ao evento query_post_execution_showplan para permitir que as definições de predicado coletassem esse evento apenas para esses cenários.
Infelizmente, isso não tem os mesmos benefícios que uma implementação como uma ação teria no desempenho. No resto deste post vou explicar o porquê.
Impacto no desempenho
Na época em que fiz os testes para o meu artigo anterior, também testei a sobrecarga associada ao evento query_post_execution_showplan, principalmente porque estava realmente interessado em usá-lo em alguns sistemas de produção do cliente e, antes disso, precisava entender o que tipo de impacto que o evento teria em sua carga de trabalho. Fiquei realmente consternado com os resultados que obtive dos meus testes originais e, depois de Aaron Bertrand validar meus resultados usando o equipamento de teste interno do SQL Sentry, arquivei outro item do Connect relatando os problemas de desempenho que foram posteriormente encerrados como "Por design" .
Para testar o impacto no desempenho, foi usada exatamente a mesma carga de trabalho e a configuração do Distributed Replay do artigo Medindo a “sobrecarga do observador” do SQL Trace vs. Extended Events. A única diferença para os resultados de teste mostrados neste artigo é que um sistema host mais novo e mais poderoso foi usado para o ambiente de VM. As VMs usadas eram exatamente as mesmas, sem alterações em sua configuração, e foram simplesmente copiadas para o novo sistema, razão pela qual a carga de trabalho de linha de base conseguiu executar a reprodução mais rapidamente com uma média de solicitações de lote/s mais alta. Os resultados da linha de base foram capturados usando uma instalação padrão do SQL Server 2012 com apenas a sessão de evento system_health padrão em execução no servidor.
Para a comparação do impacto no desempenho do
query_post_execution_showplan
evento, a seguinte definição de sessão de evento foi usada. CREATE EVENT SESSION [query_post_execution_showplan Overhead] ON SERVER ADD EVENT sqlserver.query_post_execution_showplan( WHERE ([duration]=(5000000))); GO
Esta sessão, na verdade, não coleta os dados do evento usando um destino e usa um predicado na duração da duração do evento igual a 5.000.000 microssegundos, ou cinco segundos de duração. Para a carga de trabalho de repetição, nenhuma instrução em execução tem uma duração de exatamente cinco segundos, portanto, o evento query_post_execution_showplan nunca é realmente acionado no servidor e qualquer degradação de desempenho é estritamente o resultado da coleta de dados do evento e, em seguida, da avaliação do predicado. Os resultados dos testes são mostrados na Tabela 1 e apresentados no Gráfico 2.
Tabela 1 – sobrecarga do evento query_post_execution
Gráfico 2 – sobrecarga do evento query_post_execution
Para esta rodada de testes, o desempenho da carga de trabalho diminui em aproximadamente 30% simplesmente por ter esse evento habilitado em uma sessão de evento, mesmo que ele não seja acionado para nenhum dos eventos que estão sendo reproduzidos no servidor. A degradação geral dependerá da carga de trabalho real do servidor, e é importante observar que esta série de testes reflete mais um cenário de pior caso, já que o Distributed Replay foi executado em modo de estresse e o uso da CPU no SQL Server foi atrelado em 94% em média durante os testes.
Compreendendo o impacto no desempenho
O motivo pelo qual esse evento impõe uma sobrecarga tão significativa no desempenho pode ser explicado a partir do ciclo de vida do evento em Eventos Estendidos. Quando um ponto crítico no código do SQL Server associado a um evento é encontrado durante a execução, o código executa uma verificação booleana muito rápida para determinar se o evento está habilitado em qualquer sessão de evento ativa no servidor. Se o evento estiver ativado para uma sessão de evento ativa, todas as colunas de dados associadas ao evento serão coletadas, incluindo quaisquer colunas personalizáveis que tenham sido ativadas. Neste ponto, o evento avalia quaisquer predicados para as sessões de eventos ativas que estão coletando o evento para determinar se o evento realmente será acionado completamente.
Para o evento query_post_exection_showplan, todo o impacto no desempenho é da sobrecarga associada à coleta de dados. Mesmo no caso de existir um predicado de duração igual a cinco segundos, bastando apenas ativar o evento em uma sessão de evento, é necessário coletar o Showplan XML para cada instrução que executa no servidor apenas para poder avaliar o predicado e, em seguida, determinar que o evento não será acionado. Por esse motivo, o evento query_post_execution_showplan deve ser evitado para cargas de trabalho de produção. Para a carga de trabalho de repetição de teste, o evento teve que ser avaliado aproximadamente 440.000 vezes, embora não seja realmente acionado para a carga de trabalho e a sessão de evento que está sendo testada, pois nenhum dos eventos de repetição tem duração de exatamente cinco segundos. As informações de contagem de eventos foram coletadas incluindo o destino event_counter na sessão do evento e removendo o predicado de duração e, em seguida, testando novamente a carga de trabalho de reprodução com a seguinte definição de sessão.
CREATE EVENT SESSION [query_post_execution_showplan Overhead] ON SERVER ADD EVENT sqlserver.query_post_execution_showplan ADD TARGET package0.event_counter; GO
Comparação com eventos de disparo rápido
Para fornecer um quadro de referência para esse impacto no desempenho, podemos observar a sobrecarga de ativar um conjunto de eventos executados com frequência no servidor e executar a mesma carga de trabalho de reprodução. Dois dos eventos executados com mais frequência no SQL Server são os eventos lock_acquired e lock_released. Para comparar a sobrecarga desses dois eventos, a sessão de eventos a seguir pode ser usada, que coleta os eventos sem predicado para que cada execução seja coletada e conta com que frequência eles são acionados usando o destino event_counter.
CREATE EVENT SESSION [locking Overhead] ON SERVER ADD EVENT sqlserver.lock_acquired, ADD EVENT sqlserver.lock_released ADD TARGET package0.event_counter; GO
Para nossa carga de trabalho de repetição, esses dois eventos são disparados aproximadamente 111.180.000 vezes. A sobrecarga associada à coleta desses eventos pode ser vista na Tabela 3 e no Gráfico 4.
Tabela 3 – Comparação de sobrecarga de bloqueio
Gráfico 4 – Comparação de sobrecarga de eventos de bloqueio
Como você pode ver nos dados, o efeito de desempenho desses eventos é significativamente menor do que para query_post_execution_showplan, embora a definição da sessão do evento de bloqueio tenha sido configurada para permitir que todos os eventos sejam acionados no servidor, a sobrecarga total ficou abaixo de 1% no geral . Lembre-se de que a sessão do evento de bloqueio avaliou o equivalente a 500 vezes mais eventos e, neste caso, todos os eventos realmente tiveram que ser acionados para a sessão do evento, onde o evento query_post_execution_showplan não precisou ser acionado após ser avaliado.
Resumo
Embora o evento query_post_execution_showplan forneça a capacidade de coletar o plano de consulta real para uma instrução que é executada, o impacto no desempenho da coleta de dados apenas para avaliar o evento o torna algo inviável para uso em produção. No mínimo, a sobrecarga deve ser considerada antes de você usar esse evento em uma carga de trabalho de produção. Até mesmo a descrição do evento fornecida pela Microsoft reconhece que o evento pode ter um impacto significativo no desempenho (meu destaque):
Ocorre após a execução de uma instrução SQL. Esse evento retorna uma representação XML do plano de consulta real. O uso deste evento pode ter uma sobrecarga de desempenho significativa, portanto, ele deve ser usado apenas para solucionar problemas ou monitorar problemas específicos por breves períodos de tempo.
A descrição do evento pode ser encontrada na coluna de descrição da exibição do catálogo sys.dm_xe_objects ou na interface de usuário da nova sessão, conforme mostrado na Figura 5 (meu destaque):
Figura 5 – Descrição do evento da IU da nova sessão
Eu recomendaria comparar o desempenho de qualquer evento com este aviso na descrição antes de realmente usá-lo em um ambiente de produção.