Como você limpa todos os planos de consulta antigos do Microsoft SQL Server?

12

Temos um aplicativo pronto para uso que usa um banco de dados Microsoft SQL. Nesta aplicação, escolhemos vários critérios de seleção para cada relatório. Este aplicativo, em seguida, executa esses relatórios.

Acredito que tenhamos um problema no plano de consulta. O primeiro relatório que executamos todos os dias, é executado muito rapidamente em 7 minutos. Qualquer relatório executado após o primeiro relatório leva mais de uma hora.

Todas as noites, executamos uma tarefa agendada que para e inicia o SQL Server Agent e o SQL Server. Existem aproximadamente 25 outros bancos de dados nessa instância do SQL Server. Nenhum outro banco de dados apresenta problemas de desempenho, apenas o produto de prateleira que mencionei anteriormente.

Existe uma maneira de limpar todos os planos de consulta que o SQL Server possui atualmente na memória?

Como fazer isso sem afetar 30 ou mais usuários que dependem de outros bancos de dados no mesmo servidor?

Michael Riley - também conhecido por Gunny
fonte

Respostas:

7

Peço desculpas pela minha resposta anterior.

1) Adicione a opção WITH RECOMPILE à instrução CREATE PROCEDURE se souber que sua consulta variará sempre que for executada a partir do procedimento armazenado. A opção WITH RECOMPILE impede a reutilização do plano de execução do procedimento armazenado, portanto, o SQL Server não armazena em cache um plano para esse procedimento e o procedimento é recompilado em tempo de execução. O uso da opção WITH RECOMPILE pode aumentar o desempenho se sua consulta variar sempre que for executada a partir do procedimento armazenado, pois, nesse caso, o plano de execução incorreto não será usado.

2) Você deve criar um guia de plano que use uma dica de consulta USE PLAN para cada tipo de consulta (todo tipo de solicitação de procedimento armazenado) para forçar o plano de execução.

Aqui está um artigo sobre o plano de execução que pode ajudar.

garik
fonte
Concordo em usar WITH RECOMPILE, já fiz isso com os sistemas que construí. No entanto, não tenho acesso à fonte sql ... ela é executada dentro de um aplicativo.
Michael Riley - AKA Gunny
@Cape Cod Gunny, neste caso, tente DBCC FLUSHPROCINDB: Usado para limpar o cache do procedimento armazenado para um banco de dados específico em um SQL Server, não para o SQL Server inteiro. Convém usar esse comando antes do teste para garantir que os planos de procedimentos armazenados anteriores não afetem negativamente os resultados do teste. Exemplo: DECLARAR @intDBID INTEGER SET @intDBID = (SELECT dbid FROM master.dbo.sysdatabases WHERE name = 'database_name') DBCC FLUSHPROCINDB (@intDBID)
garik
O problema foi resolvido. Verificou-se que uma tabela temporária usada para armazenar critérios de pesquisa acumulava dados perpetuamente. O processo deve truncar os dados desta tabela antes de coletar os dados. Obrigado pelo bom snippet sql.
Michael Riley - AKA Gunny
13

Você fez duas perguntas aqui. Primeiro, você deseja saber se pode remover todos os planos armazenados na memória para uma instância do SQL. Isso é feito com DBCC FREEPROCCACHE, como Matt M sugeriu.

A segunda pergunta que você fez é "Como fazer isso sem afetar 30 ou mais usuários que dependem de outros bancos de dados no mesmo servidor?". A resposta curta é "você não pode". Se você remover todos os planos, os outros usuários que dependem de planos na memória provavelmente sofrerão um impacto no desempenho.

A solução alternativa para isso requer alguma intervenção manual. Você pode usar o DBCC FREEPROCCACHE para remover planos específicos, desde que você tenha o plan_handle.

Pelo que você está descrevendo acima, parece um problema de plano, mas não tenho certeza de que remover os planos seja a resposta. Apontaria você na direção do parâmetro sniffing antes de pensar em remover planos:

http://blogs.msdn.com/b/conor_cunningham_msft/archive/2010/08/11/conor-vs-misbehaving-parameterized-queries-optimize-for-hints.aspx

Você deve otimizar as consultas em vez de brincar com o DBCC FREEPROCCACHE em uma base agendada. Também aconselho que você gaste tempo analisando os eventos de espera para sua instância.

SQLRockstar
fonte
O DBCC FREEPROCCACHE não resolveu o problema. Eu monitorei a atividade e os eventos. Existem 0 E / S físicas. Parece estar pendurado neste aplicativo: .Net Sql Client Data Provider. O tipo de espera é CXPACKET.
Michael Riley - AKA Gunny
CXPACKET implica que sua consulta está paralela. Você pode verificar quantos threads estão em execução para a consulta e examinar suas esperas? Você pode usar a ferramenta gratuita de Adam Machanic WhoIsActive sqlblog.com/files/folders/release/entry29675.aspx .
SQLRockstar 12/01
7

DBCC FREEPROCCACHE

Usando este comando, você pode limpar todo o cache do procedimento para um único comando. Definitivamente, leia a documentação antes de usar este comando. Leia a seção Observações algumas vezes.

Limpar o cache do procedimento fará com que os caches do procedimento armazenado sejam recompilados no próximo uso. Isso pode afetar o desempenho. Use com cuidado!

Matt

Matt M
fonte
Tentei usar o DBCC FREEPROCCACHE e ele não resolveu o problema. Acabei matando o processo após 1 hora.
Michael Riley - AKA Gunny