Caro [seu nome aqui]!
Oh não, desculpe-me por ouvir isso! Vamos começar com algumas noções básicas para que você se conserte rapidamente.
O que você encontra é chamado de Detecção de Parâmetros
É uma saída estranha e estranha. O nome sai da língua. Como a palavra alemã para esquilo.
E geralmente é seu amigo.
Quando uma consulta atinge seu servidor, um plano deve ser compilado. Para economizar tempo e recursos posteriormente, um plano de execução é armazenado em cache com base nas linhas estimadas que esse parâmetro fará com que seu código seja processado e retornado.
A maneira mais fácil de entender isso é imaginar um procedimento armazenado que precise contar coisas de duas populações desiguais.
Por exemplo:
Obviamente, uma execução desse código teria muito mais trabalho que outra, e os planos de consulta que você desejaria realizar quantidades totalmente diferentes de trabalho pareceriam totalmente diferentes.
O que eu estou enfrentando?
Esse é um problema genuinamente difícil de encontrar, testar e corrigir.
- É difícil de encontrar, porque isso não acontece de forma consistente
- É difícil testar porque você precisa saber quais parâmetros causam planos diferentes
- É difícil de corrigir, porque às vezes requer ajuste de consulta e índice
- É difícil de corrigir, pois talvez você não consiga alterar consultas ou índices
- É difícil de corrigir, porque mesmo que você altere consultas ou índices, ele ainda pode voltar
Correções rápidas
Às vezes, tudo que você precisa é de um pouco de clareza. Ou melhor, o cache do seu plano sim.
Se é um procedimento armazenado
Tente correr EXEC sys.sp_recompile @objname = N'schema.procname'
. Isso fará com que o procedimento recompile um novo plano na próxima vez em que for executado.
O que isso não corrigirá:
- Processos atualmente em execução.
O que isso não garante:
- O próximo processo executado após a recompilação usará um parâmetro que fornece um bom plano.
Você também pode apontar sp_recompile
para uma tabela ou exibição, mas esteja avisado de que todo o código que tocar nessa tabela ou exibição será recompilado. Isso pode dificultar muito o problema.
Se é uma consulta parametrizada
Seu trabalho é um pouco mais difícil. Você precisará rastrear o identificador SQL. Você não deseja liberar todo o cache do plano - assim como usar sp_recompile
em uma tabela ou exibição, você pode desencadear (ha ha ha) um monte de consequências indesejadas.
A maneira mais fácil de descobrir esse comando é executar sp_BlitzWho *! Há uma coluna chamada "fixar sniffing de parâmetros" que possui um comando para remover um único plano do cache. Isso tem as mesmas desvantagens da recompilação.
O que isso não corrigirá:
- Processos atualmente em execução.
O que isso não garante:
- O próximo processo executado após a recompilação usará um parâmetro que fornece um bom plano.
Eu ainda preciso de ajuda!
Vamos precisar do seguinte:
- O bom plano de consulta, se possível
- O plano de consulta incorreto
- Os parâmetros usados
- A consulta em questão
- Definições de tabela e índice
Obtendo os planos de consulta e consulta
Se a consulta estiver em execução, você pode usar sp_BlitzWho * ou sp_WhoIsActive para capturar consultas em execução no momento.
EXEC sp_BlitzWho;
EXEC sp_WhoIsActive @get_plans = 1;

Se a consulta não estiver em execução no momento, você pode procurá- la no cache do plano, usando sp_BlitzCache *.
Se você estiver no SQL Server 2016+ e tiver o Query Store ativado, poderá usar o sp_BlitzQueryStore *.
EXEC dbo.sp_BlitzCache @StoredProcName = 'Your Mom';
EXEC dbo.sp_BlitzQueryStore @StoredProcName = 'Your Mom';
Isso o ajudará a rastrear versões em cache do seu Procedimento Armazenado. Se for apenas um código parametrizado, sua pesquisa será um pouco mais difícil. Isso pode ajudar, no entanto:
EXEC dbo.sp_BlitzCache @QueryFilter = 'statement';
Você deve ver resultados bastante semelhantes de qualquer um deles. Novamente, o plano de consulta que convida a coluna clicky azul legal é seu amigo.

A maneira mais fácil de compartilhar planos é usando Colar o plano * ou despejar o XML no pastebin. Para isso, clique em uma das colunas convidativas de clique azul. Seu plano de consulta deve aparecer em uma nova guia SSMS.

Se você estiver interessado em compartilhar o código e a consulta da sua empresa, use a ferramenta Plan Explorer gratuita do Sentry One para anonimizar seu plano. Lembre-se de que isso dificulta a obtenção de ajuda - o código anonimizado é muito mais difícil de ler e descobrir.
Todas essas ferramentas sobre as quais falamos devem retornar o texto da consulta. Você não precisa fazer mais nada aqui.
Obter o (s) parâmetro (s) é um pouco mais difícil. Se você estiver usando o Plan Explorer , há uma guia na parte inferior que lista todos eles para você.

Se você estiver usando sp_BlitzCache *, há uma coluna clicável que fornece a instrução de execução para procedimentos armazenados.

Obtendo as Definições de Tabela e Índice
Você pode facilmente clicar com o botão direito do mouse no SSMS para criar um script.

Se você deseja obter tudo de uma só vez, o sp_BlitzIndex * pode ajudar se você apontar diretamente para uma mesa.
EXEC dbo.sp_BlitzIndex @DatabaseName = 'StackOverflow2010',
@SchemaName = 'dbo',
@TableName = 'Users';
Isso fornecerá a definição da tabela (embora não seja uma instrução create) e crie instruções para todos os seus índices.
Coletar e adicionar essas informações à sua pergunta deve fornecer às pessoas informações suficientes para ajudá-lo ou direcioná-lo na direção certa.
Eu quero fazer isso sozinho!
Bem, legal. Estou feliz por você. Você é uma pessoa louca.
Existem várias maneiras pelas quais as pessoas pensam "consertar" a detecção de parâmetros:
Mas isso realmente desabilita a detecção de parâmetros de maneiras diferentes. Isso não quer dizer que eles não possam resolver o problema, eles simplesmente não chegam à causa raiz.
Isso porque chegar à causa raiz geralmente é meio difícil. Você precisa procurar os "problemas de qualidade do plano" irritantes.
Começando com os planos rápidos vs lentos, procure diferenças como:
- Índices usados
- Ordem de adesão
- Serial vs Parallel
Procure também operadores diferentes que tornam seu código sensível à detecção de parâmetros:
- Pesquisas
- Classifica
- Tipo de associação
- Concessões de memória (e, por extensão, derramamentos)
- Carretéis
Não fique muito envolvido com a busca x varredura, a fragmentação do índice ou qualquer material que as pessoas cultuam e vasculham.
Geralmente, há um problema de indexação bastante básico. Às vezes, o código precisa ser reescrito um pouco.
Se você quiser saber mais sobre a detecção de parâmetros:
Se você está lendo isso e acha que perdi um link ou uma ferramenta útil, deixe um comentário. Eu farei o meu melhor para manter isso atualizado.