Lentidão repentina do SQL Server 2014 / Sem inserções / Não relacionado ao hardware ou índice

8

Estou executando um 350GBbanco de dados no meu PC com ~ 40 milhões de linhas.

SQL Server 2014, Win7, AMD 8350 a 4.8GHZ, 16 GB de RAM e um SSD de 500 GB (o banco de dados está hospedado em seu próprio SSD de 500 GB, com uma taxa de transferência de 500 MB / 500 MB de leitura / gravação).

O banco de dados não está sendo atualizado, estou apenas analisando / lendo. Com a criação de alguns indexes, alguns join, count(*)etc, leva menos de 1 minuto, o que é bom para meus propósitos. Fiz algumas consultas (depois de executar uma única consulta de junção, 40 a 50 vezes, fica lenta) nos dados e agora as chamadas que demoraram 1 minuto ainda estão sendo executadas 20 minutos depois.

Fico atento aos recursos do sistema e consigo ver SSDquando a consulta é iniciada, ela lê por 20 a 30 segundos e depois 121kB/secondpelos próximos 20 minutos. Este não é um problema de CPU ou disco. Estou limitado com minha quantidade de RAM, no entanto, as chamadas funcionam bem quando carreguei o banco de dados, agora, nada é executado, 25 minutos depois.

Efetivamente, não posso mais consultar o banco de dados, qualquer chamada leva tempo demais, mesmo uma SELECTdeclaração básica . Eu tentei reconstruir os índices e atualizar as estatísticas, mas não há diferença.

Como não tenho muita experiência nisso, é perfeitamente possível que minha consulta SQL esteja incorreta; nesse caso, eu esperaria um erro ou a execução com 0 resultados, mas nenhuma delas ocorre.

O que estou tentando fazer é contar todas as instâncias de um 'TypeID', nos 5 segundos anteriores a um horário com base na tabela ACALLS.

SELECT ACALLS.StartTime, ACALLS.Time, ACALLS.ServerIP, ACALLS.SRVR,   ACALLS.calls, ACALLS.TOKEN, COUNT(TypeID) as ExecRate
FROM ACALLS
INNER JOIN MAINVIEW ON 
MainView.TimeStamp BETWEEN ACALLS.StartTime and DATEADD(ss,-5,ACALLS.StartTime)

WHERE DATEPART(hour,MainView.TimeStamp) BETWEEN 10 and 13 and 
CAST(MainView.TimeStamp as date) = '2015-12-09' and
MainView.TypeID = '123456789'
GROUP BY Acalls.STartTime, ACALLs.TIME, ServerIp,SRVR, ACALLS.CALLS, ACALLS.TOKEN
ORDER BY Acalls.StartTime

Depois de executar "Quem está executando", insira a descrição da imagem aqui insira a descrição da imagem aqui


fonte
Eu suspeito que isso tenha a ver com as estatísticas nas tabelas e os tipos de processamento feitos para as junções. Você deve examinar os planos de execução para as consultas: junções de loop aninhadas podem ser um sinal de problemas.
Gordon Linoff
Você já tentou com RECOMPILE?
3
Poste um plano de execução real de uma consulta surpreendentemente lenta. Quanto mais simples a consulta, melhor.
usr
11
Você atualizou as estatísticas de todas as tabelas? Você reconstruiu todos os índices? Informações sobre sp_whoisactive: link
TT.
2
Essas estatísticas de espera mostram muito IO, mas não sabemos qual proporção da consulta é IO e qual é a CPU. Execute os testes que eu recomendei após os resultados.
usr

Respostas:

2

Você tem uma consulta que não é SARGable - mesmo se você tiver bons índices, não os estará usando com essa consulta.

Primeiro, uma reação instintiva ao pageiolatch_sh é ler páginas do disco no buffer; você não tem RAM suficiente para os dados que está tentando extrair.

Segundo, você precisa examinar o plano de execução e seu uso de índices - ou a falta dele.

Pare de usar funções em suas junções e em seu WHERE e obtenha apenas os dados absolutamente necessários para começar.

  • "ENTRE ACALLS.StartTime e DATEADD (ss, -5, ACALLS.StartTime)" - livre-se desse DATEADD entre BETWEEN.

    • Se este for um banco de dados de relatórios somente leitura, crie uma tabela de relatórios apenas com os dados necessários e, em seguida, coloque índices compostos conforme necessário. Use esse para obter as chaves primárias / outras chaves exclusivas das linhas ACALLS necessárias e, em seguida, obter o restante dos dados ACALLS posteriormente.
  • WHERE DATEPART (hora, MainView.TimeStamp) ENTRE 10 e 13 e CAST (MainView.TimeStamp como data) = '2015-12-09'

    • mesma coisa - livrar-se do CAST - altere '2015-12-09' para um ou dois @ parâmetros do tipo de dados correto para MainView.TimeStamp> = @StartTimestamp AND MainView.TimeStamp <@EndTimestamp

    • e livre-se desse DATEPART restringindo @StartTimestamp e @EndTimestamp para incluir também os critérios de horário.

Talvez carregue uma tabela #temp apenas com as chaves primárias / exclusivas das linhas que atendem aos critérios do MainView antes da associação.

Hmm ... também, se Mainview for uma visão complexa, vá direto para as tabelas base para carregar a tabela #temp

Não se esqueça de usar o Profiler para verificar e ver se adicionar índices (compostos, se necessário) na #temp ou em outra tabela de preparação é um ganho líquido ou uma perda líquida :).

Senhas anti-fracas
fonte
1

crie um índice não clusterizado composto na visualização principal (typeid, timestamp).

altere seu "where" no mainview para não usar uma função nas colunas do mainview. isso pode exigir que você pré-calcule esses valores como variáveis ​​antes de executar a consulta, se precisar que eles sejam mais dinâmicos.

WHERE MainView.TimeStamp BETWEEN '2015-12-09 10:00' and '2015-12-09 13:00'

crie um índice não clusterizado em ACALLS.StartTime.

altere a junção para ACALLS to be

WHERE ACALLS.StartTime BETWEEN DATEADD(ss,-5,MainView.TimeStamp) AND MainView.TimeStamp

pelo meu entendimento, isso manipulará sua lógica e se unirá a um desempenho bastante alto e afastará você do IO.

meu melhor palpite sobre o que você está enfrentando é que seus dados estão sendo liberados do cache e / ou o tempdb está sendo derramado no disco de vez em quando, então a melhor solução que eu normalmente encontrei é escrever as consultas melhor limitar o tempdb e uso de memória e os problemas subjacentes desaparecem.

Bruce Dunwiddie
fonte