Eu tenho um procedimento armazenado que retorna resultados de uma exibição indexada por meio de um índice de cobertura. Geralmente, ele é executado rapidamente (~ 10 ms), às vezes pode demorar até 8 segundos.
Aqui está um exemplo de execução aleatória (nota: não é lenta, mas o texto da consulta é o mesmo, exceto o valor passado):
declare @p2 dbo.IdentityType
insert into @p2 values(5710955)
insert into @p2 values(5710896)
insert into @p2 values(5710678)
insert into @p2 values(5710871)
insert into @p2 values(5711103)
insert into @p2 values(6215197)
insert into @p2 values(5710780)
exec ListingSearch_ByLocationAndStatus @statusType=1,@locationIds=@p2
Aqui está o SPROC:
ALTER PROCEDURE [dbo].[ListingSearch_ByLocationAndStatus]
@LocationIds IdentityType READONLY,
@StatusType TINYINT
AS
BEGIN
SET NOCOUNT ON;
SELECT -- lots of fields
FROM [dbo].[ListingSearchView][a] WITH (NOEXPAND)
INNER JOIN @LocationIds [b] ON [a].[LocationId] = [b].[Id]
WHERE [a].[StatusType] = @statusType
OPTION (RECOMPILE);
(nota: eu adicionei a OPTION (RECOMPILE)
dica recentemente após alguns conselhos, mas não ajudou.
Aqui está o índice de cobertura (observação: a exibição também possui um índice em cluster ListingId
, que é único)
CREATE NONCLUSTERED INDEX [IX_ListingSearchView_ForAPI] ON [dbo].[ListingSearchView]
(
[LocationId] ASC,
[StatusType] ASC
)
INCLUDE ( -- all the fields in the query) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO
Coloquei um rastreamento de criador de perfil, com estatísticas XML do showplan.
Aqui está um processo lento (6 segundos) e o plano relevante:
Parece exatamente como eu esperava e é o mesmo plano quando a consulta é rápida.
Aqui está o zoom na parte cara do plano, se isso ajudar:
Aqui está o esquema completo das tabelas de visualização / backup, se isso ajudar: https://pastebin.com/wh1sRcbQ
Notas:
- Os índices foram desfragmentados, as estatísticas atualizadas.
- Originalmente, a consulta estava embutida na visualização, mas mudei para o SPROC para tentar ajudar a estabilizar. Não ajudou.
- Adicionando
WITH OPTION (RECOMPILE);
dica (não funcionou, por isso não pode ser farejador de parâmetros?) - Outras consultas no sistema também às vezes são lentas e também não apresentam problemas óbvios em seu plano.
- Pode estar travando? Não tenho certeza de como confirmar.
Alguma idéia sobre o que eu poderia tentar a seguir?
obrigado
Respostas:
Eu realmente não acho que usar o
OPTION (RECOMPILE)
é uma maneira eficaz de eliminar a possibilidade de cheirar parâmetros.A detecção de parâmetros ocorre quando o SQL está confuso sobre uma consulta específica e pensa que é novo porque vê novos parâmetros. É lento porque está demorando mais para gerar um novo plano de execução.
Tudo o que essa opção faz é forçar o SQL a produzir um novo plano sempre que é praticamente a mesma coisa. Em vez disso, você pode considerar adicionar parâmetros padrão usando esta dica:
Ao escolher parâmetros para o padrão, certifique-se de usar um conjunto estatisticamente representativo.
Isso forçará o mesmo plano a ser usado todas as vezes e eliminará a possibilidade de detecção de parâmetros. Depois de fazer isso e determinar que não ajudou, provavelmente é seguro descartar o sniffing de parâmetros como uma possibilidade.
fonte
Talvez tente forçar a ordem, então você provavelmente está sempre começando com a tabela menor (variável). Isso fica complicado com vistas ...
ou você pode forçar uma junção de loop, se é geralmente assim que você deseja associar a variável de tabela à visualização, o que também forçará a ordem ...
fonte
Escreva o nome do procedimento Store no Query Editor e selecione o processo Store. nome e, em seguida, selecione o plano Exibir execução estimada ou clique em (Ctrl + L). abaixo da imagem disso.
os planos de execução são exibidos ao lado da guia Mensagens na parte inferior do Query Editor. nas linhas de cor verde, mostre os detalhes ausentes do índice e clique com o botão direito do mouse. Em seguida, nova consulta é aberta em uma nova guia e cria o índice. sua consulta será executada rapidamente.
Então, eu usei esse método para diagnosticar a consulta que trabalham devagar. e também existem tantas consultas ou métodos que você pode usar.
fonte
Se você acha que o problema está no bloqueio, sugiro que você use o Read Optimized Snapshot de nível de isolamento da transação (lembre-se de que isso sobrecarregará o tempDB).
REFERÊNCIA: https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/snapshot-isolation-in-sql-server
Se o problema não está no bloqueio de leitura / gravação, você pode tentar adicionar índices na sua exibição (a melhor escolha de índices depende da seletividade dos seus dados)
fonte
IX_ListingSearchView_ForAPI
(veja o script na pergunta).