TSQL: Encontre consultas que causam muitas compilações SQL e recompilações SQL separadamente

8

Quero descobrir o que está causando as altas compilações SQL (não as recompilações) que estou vendo nos contadores do monitor de desempenho.

Aqui está minha opinião: se estou vendo muitas compilações SQl, significa que as consultas em nosso sistema não estão sendo armazenadas em cache pelos seguintes motivos:

  • Muitas consultas ad-hoc
  • Executando consultas que o SQl não armazena em cache, por exemplo:

    UPDATE table1 SET col1 = 'String com mais de 8000 caracteres .....' WHERE key_column = some int

  • Os planos expiram e estão sendo removidos do cache porque: O cache está ficando sem espaço ou os planos não estão sendo usados ​​por tempo suficiente.

A única coisa que se aproxima da captura de inserções de cache no criador de perfil é Procedimentos armazenados-> SP: CacheInserts, mas ele apenas cuida do cache do procedimento armazenado.

Então, tentei o seguinte para obter consultas ad-hoc:

SELECT [cp].[refcounts] -- when Refcounts becomes 0, plan is excluded from cache.
    , [cp].[usecounts] 
    , [cp].[objtype] 
    , st.[dbid] 
    , st.[objectid] 
    , st.[text] 
    , [qp].[query_plan] 
FROM sys.dm_exec_cached_plans cp     
CROSS APPLY sys.dm_exec_sql_text ( cp.plan_handle ) st     
CROSS APPLY sys.dm_exec_query_plan ( cp.plan_handle ) qp ;

Eu pensei que as consultas que causaram as compilações deveriam ser aquelas com objtype = Adhoc, mas isso também pode estar relacionado a recompilações. Agora eu tenho que executar o criador de perfil, capturar consultas causando recompilações e, em seguida, extraí-lo da lista acima.

Estou indo na direção certa?

Existe uma única consulta que posso usar para obter apenas compilações SQL sem muito trabalho?

Recursos que me ajudaram a obter o conhecimento acima:

http://social.msdn.microsoft.com/Forums/en/sqldatabaseengine/thread/954b4fba-3774-42e3-86e7-e5172abe0c83 http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=143946 http: //technet.microsoft.com/en-nz/library/cc966425(en-us).aspx
http://www.sqlservercentral.com/Forums/Topic914951-360-1.aspx

Qualquer ajuda é realmente apreciada.

Manjot
fonte

Respostas:

7

Eu não acho que você pode encontrar isso de uma maneira fácil, mas é possível, de qualquer maneira, superar isso. O Profiler oferece muitos tipos de classe de eventos que podem ser usados ​​na análise do desempenho de uma consulta. Inicie uma nova sessão do Profiler e verifique os seguintes eventos:

Performance: Performance statistics
Stored Procedures: RPC:Completed
TSQL: SQL:BatchCompleted
TSQL: SQL: BatchStarting

Marque Mostrar todas as colunas e selecione cada uma das colunas em Desempenho: somente evento de estatísticas de desempenho. O restante dos eventos pode ser deixado com a configuração padrão.

Em seguida, selecione Filtros de coluna e filtre por DatabaseName e / ou LoginName / ApplicationName / HostName etc., se você os conhecer. O objetivo é limitar o número de linhas expostas no Profiler e concentrar-se apenas nas suas necessidades.

Em seguida, pressione Executar e deixe-o funcionar por um tempo (2-3 minutos, conforme necessário). Analise os resultados exibidos exibindo principalmente: Evento de estatísticas de desempenho.

Se as Estatísticas de desempenho ocorrerem com frequência, significa que o plano de uma consulta foi armazenado em cache pela primeira vez, compilado, recompilado ou despejado do PlanCache. Pelo que sei, se uma consulta não tiver seu plano de consulta no Planejar Cache - você verá 2 linhas do evento PerformanceStatistics e será seguido por SQL: BatchStarting e SQL: BatchCompleted . Isso significa que o plano de consulta foi primeiro compilado, armazenado em cache e, em seguida, a consulta foi iniciada e concluída.

Observe as seguintes colunas no evento Estatísticas de Desempenho:

SPID - ID of the session on which the event occurred. You can use it to identify the       
       row on SQL:BatchCompleted event which will display the SQL Query text and other  
       usefull information (Read/Writes, StartTime/EndTime)
Duration - Total time, in microseconds, spent during compilation.
EventSubClass - 0 = New batch SQL text that is not currently present in the cache.
                1 = Queries within a stored procedure have been compiled.
                2 = Queries within an ad hoc SQL statement have been compiled.
                3 = A cached query has been destroyed and the historical performance         
                    data associated with the plan is about to be destroyed.
                4 = A cached stored procedure has been removed from the cache and the  
                    historical performance data associated with it is about to be 
                    destroyed.

                5 = A cached trigger has been removed from the cache and the historical  
                    performance data associated with it is about to be destroyed.

Considerando o número EventSubClass, você pode descobrir o que aconteceu com o Plano de Consulta e tomar medidas específicas. Além disso, você pode adicionar outras colunas aos Procedimentos Armazenados e às Classes de Eventos TSQL se estiver interceptado em HostName, WindowsUser ou outras informações do rastreamento do Profiler. Além disso, o rastreamento pode ser armazenado em uma tabela SQL, tornando a análise mais fácil e muito mais personalizável. Aqui está um link que descreve mais a Classe de Eventos de Estatísticas de Desempenho.

yrushka
fonte
4

Bem, primeiro vamos ver se há pressão no cache.

select bpool_visible from sys.dm_os_sys_info
go

Multiplique esse número por 8 para obter a memória em K. 75% disso de 0-4G + 10% disso de 4G-64G + 5% de mais é o limite de pressão do cache planejado . Se você atingir 75% desse limite, o SQL Server começará a limpar os planos do cache. Essa eliminação ocorre quando um novo plano de consulta é adicionado ao cache, para que o encadeamento seja pausado para fazer esse trabalho. A segunda coisa que pode fazer com que os planos sejam eliminados é se o número de planos exceder 4x o número de depósitos de hash (uma tabela de hash mapeia uma plan_handle para um plano). Existem 10.000 em um sistema de 32 bits e 40.000 em um sistema de 64 bits.

select type, sum(pages_allocated_count) as pages_used from sys.dm_os_memory_objects 
where type in ('MEMOBJ_CACHESTOREOBJCP', 'MEMOBJ_CACHESTORESQLCP', 'MEMOBJ_CACHESTOREXPROC')
group by type
go

A decisão sobre o que eliminar não é tomada no uso, mas no custo do plano, os planos mais baratos são eliminados primeiro (custo de produção, não execução). Você pode ver isso se adicionar as colunas original_coste current_costa sua consulta em sys.dm_exec_cached_plans. Um plano ad-hoc começa em 0 e é incrementado em 1 toda vez que é usado. Quando a pressão do cache ocorre, o SQL Server subtrai metade de cada custo e limpa os que atingiram 0.

Se você possui muitas SQL ad-hoc, tente:

exec sp_reconfigure 'optimize for ad hoc workloads', 1
go
reconfigure
go

Nesse modo, o SQL Server armazena em cache apenas um "stub", com aproximadamente 300 bytes de tamanho (um plano de consulta normal é mínimo de 24k), contendo um hash e um ponteiro para o texto SQL, na primeira vez em que vê uma instrução SQL específica e, em seguida, posteriormente, armazena em cache o plano completo se for executado novamente. Isso não reduzirá necessariamente as compilações por si só, mas aliviará a pressão da memória no cache do plano.

Nota: Isso funciona em 2008, não tentei em 2005.

Outro truque é

alter database ... set parameterization forced
go

Isso fará com que o SQL Server trate constantes como parâmetros, o que pode ajudar com o recurso de parametrização automática que normalmente armazena em cache os planos para instruções SQL semelhantes. O SQL ad-hoc deve ter seus planos de consulta em cache, a menos que o servidor tenha muito pouca memória, mas isso depende de correspondências textuais exatas, a menos que possa ser parametrizado; nesse caso, ele se comporta mais como uma consulta preparada.

Gaius
fonte
Obrigado! Eu conhecia essa opção de "parametrização forçada", mas estava com medo de usá-la. A única desvantagem que posso ver ao usar isso é que ele irá preencher o cache. Estou certo?
Manjot
3

Você tem muitos trabalhos do SQL Server em execução frequentemente nesta caixa? Observe que em 2005 as consultas de trabalho do agente NÃO são armazenadas em cache e também podem causar inchaço no cache e compilações sql.

Veja o número de planos com baixa contagem de reutilização. Esses são seus culpados.

Algumas notas relacionadas sobre o planejamento do cache abaixo.

http://www.sqlskills.com/BLOGS/KIMBERLY/post/Plan-cache-adhoc-workloads-and-clearing-the-single-use-plan-cache-bloat.aspx

http://www.sqlskills.com/BLOGS/KIMBERLY/post/Clearing-the-cache-are-there-other-options.aspx

Sankar Reddy
fonte
0

Esse efeito é conhecido como "poluição do plano de consulta", onde muitas consultas SQL semelhantes geram planos de execução separados, mas equivalentes.

As consultas ad-hoc causam sobrecarga pela análise individual, mas geralmente não poluem o plano de consulta, pois seus planos não são armazenados. Isso é diferente para consultas com apenas um parâmetro (no MS SQL Server); elas serão tratadas como uma consulta parametrizada.

Existem alguns casos típicos de poluição do plano de consulta:

  • Consultas SQL com apenas um parâmetro literal codificado (como 'selecionar id, nome da pessoa em que id = 1234')
  • especialmente se usado com comandos / procedimentos armazenados que forçam o banco de dados a armazenar o plano de consulta, como 'sp_prepexec' ou sp_executesql 'no MSSQL (acho que' execute imediato 'no Oracle funciona de maneira semelhante)
  • consultas parcialmente parametrizadas, com grande variação nos valores literais 'codificados', como 'select * de SoccerMatches sm onde sm.Date>?' e sm.Date <? e HomeClubId = 5678 e GuestClubId = 1234 '. Isso salvará os planos de consulta devido aos parâmetros, mas criará um novo plano de consulta para cada HomeClub ou GuestClub alterado (especialmente porque os valores de Data / Hora são uma ótima ocasião para introduzir parâmetros em muitas APIs de banco de dados, quando as consultas falham devido a uma data localmente diferente formatos).
  • Outra fonte de poluição do plano de consulta pode ser estruturas como o ADO.NET com drivers insuficientes, em combinação com valores de string / (n) varchar. Algumas implementações / drivers definirão os tamanhos dos parâmetros para o comprimento real da string, causando um plano de consulta separado para cada comprimento diferente de parâmetro da string na consulta. A melhor prática parece ser o uso do tamanho máximo do campo (por exemplo, varchar (4000)) ou um driver que coloque um comprimento correto
Erik Hart
fonte