A maioria dos planos de consulta recriados nas últimas 4 horas

9

Estou com um problema no desempenho do meu banco de dados SQL Server. Eu encontrei esta ferramenta sp_BlitzCache . Após a execução do comando, recebi esta declaração:

Você tem planos de 92,00% criados nas últimas 24 horas e 92,00% criados nas últimas 4 horas.

Enquanto identifiquei o problema (usando o SQL Server Profiler, verifiquei as ocorrências de eventos StmtRecompile), consegui encontrar apenas algumas consultas de pesquisa de texto completo que geralmente são reconstruídas. No entanto, as consultas de pesquisa de texto completo representam apenas cerca de 5% de todas as consultas.

Você tem alguma sugestão do que pode causar a recriação dos demais planos de 87%?

Eu tenho o SQL Server 2012 (versão 11.0.6567.0).

Editar: adicionei meus contadores de desempenho

+---------------------------+--------------------------------+--------------+
|        object_name        |          counter_name          |  cntr_value  |
+---------------------------+--------------------------------+--------------+
| SQLServer:Buffer Manager  | Background writer pages/sec    |            0 |
| SQLServer:Buffer Manager  | Buffer cache hit ratio         |        28436 |
| SQLServer:Buffer Manager  | Buffer cache hit ratio base    |        28436 |
| SQLServer:Buffer Manager  | Checkpoint pages/sec           |      8259452 |
| SQLServer:Buffer Manager  | Database pages                 |      4434337 |
| SQLServer:Buffer Manager  | Free list stalls/sec           |            9 |
| SQLServer:Buffer Manager  | Integral Controller Slope      |            0 |
| SQLServer:Buffer Manager  | Lazy writes/sec                |         5608 |
| SQLServer:Buffer Manager  | Page life expectancy           |       438901 |
| SQLServer:Buffer Manager  | Page lookups/sec               | 122694703703 |
| SQLServer:Buffer Manager  | Page reads/sec                 |     60994608 |
| SQLServer:Buffer Manager  | Page writes/sec                |    126076564 |
| SQLServer:Buffer Manager  | Readahead pages/sec            |     45305420 |
| SQLServer:Buffer Manager  | Target pages                   |    130990080 |
| SQLServer:Buffer Node     | Database pages                 |      4434337 |
| SQLServer:Buffer Node     | Page life expectancy           |       438901 |
| SQLServer:Buffer Node     | Local node page lookups/sec    |            0 |
| SQLServer:Buffer Node     | Remote node page lookups/sec   |            0 |
| SQLServer:Memory Manager  | External benefit of memory     |            0 |
| SQLServer:Memory Manager  | Connection Memory (KB)         |         3304 |
| SQLServer:Memory Manager  | Database Cache Memory (KB)     |     35474784 |
| SQLServer:Memory Manager  | Free Memory (KB)               |     13229808 |
| SQLServer:Memory Manager  | Granted Workspace Memory (KB)  |            0 |
| SQLServer:Memory Manager  | Lock Memory (KB)               |       455928 |
| SQLServer:Memory Manager  | Lock Blocks Allocated          |      1798154 |
| SQLServer:Memory Manager  | Lock Owner Blocks Allocated    |      3568588 |
| SQLServer:Memory Manager  | Lock Blocks                    |        10562 |
| SQLServer:Memory Manager  | Lock Owner Blocks              |        10617 |
| SQLServer:Memory Manager  | Maximum Workspace Memory (KB)  |     43368000 |
| SQLServer:Memory Manager  | Memory Grants Outstanding      |            0 |
| SQLServer:Memory Manager  | Memory Grants Pending          |            0 |
| SQLServer:Memory Manager  | Optimizer Memory (KB)          |         1400 |
| SQLServer:Memory Manager  | Reserved Server Memory (KB)    |            0 |
| SQLServer:Memory Manager  | SQL Cache Memory (KB)          |       229112 |
| SQLServer:Memory Manager  | Stolen Server Memory (KB)      |      8063232 |
| SQLServer:Memory Manager  | Log Pool Memory (KB)           |         4192 |
| SQLServer:Memory Manager  | Target Server Memory (KB)      |     56934400 |
| SQLServer:Memory Manager  | Total Server Memory (KB)       |     56767824 |
| SQLServer:Memory Node     | Database Node Memory (KB)      |     35474784 |
| SQLServer:Memory Node     | Free Node Memory (KB)          |     13229808 |
| SQLServer:Memory Node     | Foreign Node Memory (KB)       |            0 |
| SQLServer:Memory Node     | Stolen Node Memory (KB)        |      8063208 |
| SQLServer:Memory Node     | Target Node Memory (KB)        |     56934376 |
| SQLServer:Memory Node     | Total Node Memory (KB)         |     56767800 |
+---------------------------+--------------------------------+--------------+
Marcin Topolewski
fonte
Talvez alguém tenha executado o DBCC FREEPROCCACHE? : P
Daniel Björk
@ DanielBjörk Eu sou a única pessoa que tem permissão para fazer coisas assim, então não acho que seja o motivo. No entanto, vou verificar.
Marcin Topolewski
Você está usando consultas parametrizadas ou procedimentos armazenados? ou o problema é que você tem literais de string / número no SQL e, portanto, os planos não podem ser reutilizados?
James Z
@ JamesZ Sim, estou usando muitas consultas parametrizadas. A ferramenta que mencionei no meu post, BlitzCache, diz que tenho um problema com o sniffing de parâmetros.
Marcin Topolewski
11
Você está reconstruindo índices ou atualizando estatísticas todas as noites? Talvez haja pressão de memória no servidor?
Erik Darling

Respostas:

6

A consulta usada para testar o tempo de criação do plano é esta

WITH x AS (
SELECT SUM(CASE WHEN DATEDIFF(HOUR, deqs.creation_time, SYSDATETIME()) <= 24 THEN 1 ELSE 0 END) AS [plans_24],
       SUM(CASE WHEN DATEDIFF(HOUR, deqs.creation_time, SYSDATETIME()) <= 4 THEN 1 ELSE 0 END) AS [plans_4],
       SUM(CASE WHEN DATEDIFF(HOUR, deqs.creation_time, SYSDATETIME()) <= 1 THEN 1 ELSE 0 END) AS [plans_1],
       COUNT(deqs.creation_time) AS [total_plans]
FROM sys.dm_exec_query_stats AS deqs
)
SELECT CONVERT(DECIMAL(3,2), NULLIF(x.plans_24, 0) / (1. * NULLIF(x.total_plans, 0))) * 100 AS [percent_24],
       CONVERT(DECIMAL(3,2), NULLIF(x.plans_4 , 0) / (1. * NULLIF(x.total_plans, 0))) * 100 AS [percent_4],
       CONVERT(DECIMAL(3,2), NULLIF(x.plans_1 , 0) / (1. * NULLIF(x.total_plans, 0))) * 100 AS [percent_1],
       @@SPID AS SPID
INTO #plan_creation
FROM x
OPTION (RECOMPILE) ;

o SP também fornece algumas dicas sobre por onde começar sua pesquisa

Se essas porcentagens forem altas, pode ser um sinal de pressão da memória ou planejar instabilidade do cache

Além das dicas acima, verifique se o servidor foi reiniciado.

se o seu servidor não for reiniciado, abaixo está a abordagem que eu adotaria

  • verifique se a sua pressão de memória

Primeiro, veja se as configurações de memória estão definidas da melhor maneira possível.

Memória: MB disponível em
buffer SQL: páginas gratuitas
Buffer SQL: vida
útil da página Buffer SQL: gravações preguiçosas

se você estiver enfrentando pressão de memória, poderá ver e ajustar as consultas que estão usando mais memória ou tentar adicionar mais memória

você pode ter executado consultas que causam recompilação. algumas delas incluem

  • Alterações feitas em uma tabela ou exibição referenciada pela consulta (ALTER TABLE e ALTER VIEW).

  • Alterações feitas em um único procedimento, o que eliminaria todos os planos desse procedimento do cache (ALTER PROCEDURE).

  • Alterações em quaisquer índices usados ​​pelo plano de execução

  • Atualizações nas estatísticas usadas pelo plano de execução, geradas explicitamente a partir de uma instrução, como UPDATE STATISTICS, ou geradas automaticamente.

  • Descartar um índice usado pelo plano de execução.

Você também pode ver este white paper para obter mais detalhes sobre o planejamento do cache

https://technet.microsoft.com/en-us/library/ee343986(v=sql.100).aspx

TheGameiswar
fonte
Adicionei meus contadores de desempenho. Você poderia me ajudar a interpretar esses valores?
Marcin Topolewski
você pode olhar para fora contadores de memória relacionada detalhados aqui: blogs.msdn.microsoft.com/teekamg/2007/11/06/...
TheGameiswar
@TheGameiswar, você diz "você pode ter executado consultas que causam recompilação ... como alterações no índice, atualização nas estatísticas". Se eu indexar reorganizar / reconstruir com base em estatísticas de fragmentação + atualização todas as noites, isso significa que meus planos serão todos (ou quase todos) recriados todos os dias? isso é um problema?
Danielle Paquette-Harvey
2

Para adicionar o que o @TheGameiswar disse, você também pode executar esta consulta para ver os detalhes dos planos que não são obtidos do cache.

;with
    xmlnamespaces (N'http://schemas.microsoft.com/sqlserver/2004/07/showplan' as DYN)
select
    db_name(st.dbid) as DBName
    , object_schema_name(st.objectid, st.dbid) as SchemaName
    , object_name(st.objectid, st.dbid) as ObjectName
    , ecp.objtype
    , st.text
    , qp.query_plan.value('(/DYN:ShowPlanXML/DYN:BatchSequence/DYN:Batch/DYN:Statements/DYN:StmtSimple/@RetrievedFromCache)[1]', 'varchar(100)') as RetrievedFromCache
    , qp.query_plan
into #temp
from sys.dm_exec_cached_plans ecp
    outer apply sys.dm_exec_query_plan(ecp.plan_handle) qp
    outer apply sys.dm_exec_sql_text(ecp.plan_handle) st

select
    *
from #temp t
where t.RetrievedFromCache is null
    and t.DBName is not null
order by t.DBName, t.SchemaName, t.ObjectName;
Dean Savović
fonte