Pode acontecer que uma pequena quantidade de dados atinja um determinado limite no SQL Server para forçar outro plano ou algo assim. Isso não é improvável. Mas o fato de seu disco parecer estar pesadamente sob serviço me leva a outra conclusão.
Existem 2 razões básicas possíveis para o seu abrandamento.
- Você atualizou seu sistema e o reinicializou
- Você carrega um monte de dados nele
Vamos dar uma olhada na parte nº 1
Pode ser que sua configuração do SQL Server esteja quebrada. Isso pode causar sérios problemas em relação à velocidade do servidor e ao uso do disco.
Por favor, verifique na primeira instância as configurações básicas do servidor. Essas configurações básicas são max server memory,affinity I/O mask , affinity maske max degree of parallelism. Pode ser necessário ativar as opções avançadas usando show advanced options.
Aqui está um script completo:
-- enable advanced options
EXEC sp_configure 'show advanced options',1
-- apply configuration
RECONFIGURE
-- how much memory can the sql server allocate?
EXEC sp_configure 'max server memory'
-- which cpu is used to run I/O operations
EXEC sp_configure 'affinity I/O mask'
-- which cpus can run processes?
EXEC sp_configure 'affinity mask'
-- how many threads can work on one query part?
EXEC sp_configure 'max degree of parallelism'
Compare o resultado com seus valores documentados em suas etapas de instalação. Eles ainda são os mesmos?
Pode haver muitos motivos pelos quais o servidor se comporta de maneira estranha. Eu normalmente apostaria que seumax server memory está errado. Isso fará com que o SQL Server troque permanentemente as páginas de dados. Ele não pode guardar tudo em sua memória. Isso significa que ele precisa ler as páginas do disco, atualizá-lo e escrevê-lo instantaneamente. Se outra atualização aparecer e usar a mesma página para uma atualização, ela não poderá ser lida na memória. Em vez disso, o servidor precisa lê-lo novamente no disco. Apenas trocando ...
Outro problema pode ser uma alta afinidade no disco ou nos processos. Se você usou um servidor compartilhado (SQL Server + outros serviços) com um disco dedicado para o SQL Server (que pode ser um caso raro, mas pode ser), esse pode ser o seu problema. Seu servidor costumava ter, por exemplo, 3 cpus para processos e um para E / S. Os outros 12 cpus são usados para outros serviços. Nesse caso, sua máscara de afinidade está errada e usa, por exemplo, uma configuração automática. Isso significa que o servidor utiliza todos os 16 núcleos para processos e E / S dinamicamente. Se você tiver grandes processos em execução, eles podem colocar uma carga enorme no disco, o que pode não ser possível. Mas, na verdade, não acredito que este seja o seu caso. Seria mais rápido (mesmo que apenas um pouco) se isso se aplicasse, mas o seu caso é mais lento.
Outro problema pode ser um alto grau de paralelismo. O que significa que você tem muitos threads ociosos em uma parte parcial de uma consulta. Isso também pode causar uma grande desaceleração se o paralelismo não funcionar como esperado. Mas isso não descreverá sua E / S alta no total.
Agora vamos dar uma olhada na parte n ° 2 também
Você carrega várias linhas no seu sistema. Mesmo que esse seja um trabalho regular, ele pode aumentar um limite no qual seus planos de consulta aumentam. Pode até ser o caso de sua inserção em combinação com o SQL Server produzir esse comportamento.
Você mencionou que já tentou migrar seus índices para outro disco, o que parece ajudar. Isso pode acontecer apenas pelo fato de você dividir a carga em dois discos diferentes.
Pode ser que seus índices estejam fraturados, que seus planos estejam fraturados ou que suas estatísticas estejam desatualizadas.
1. permite verificar a última atualização das estatísticas
Você pode fazer isso manualmente na interface para cada elemento estatístico. O que seria uma dor. Ou você pode tentar este código:
SELECT name AS indexname,
STATS_DATE(OBJECT_ID, index_id) AS StatsUpdated
FROM sys.indexes
Isso fornecerá informações completas sobre cada índice (e pilha) e as estatísticas por trás deles. Mesmo se você executar sp_updatestats, isso não significa que as estatísticas foram atualizadas. A parte em que uma atualização é bastante complicada, mesmo se você executar sp_updatestatsou mesmo se auto update statisticsestiver ativado, as estatísticas não serão atualizadas a tempo. Aqui estão alguns pontos de vantagem, quando uma atualização é necessária / gerada:
- Uma tabela vazia obtém uma ou mais linhas
- Uma tabela com mais de 500 linhas atualiza 20% + 500 linhas adicionais e ocorreu uma inserção depois
- Quando 500 linhas foram alteradas em uma tabela que contém menos de 500 linhas
Isso significa que suas estatísticas podem estar desatualizadas, mesmo se você executar a atualização.
Você pode dar uma olhada na consulta acima. Se você encontrar algumas estatísticas bastante antigas em algumas tabelas, convém executar uma atualização estatística manual para esta tabela:
UPDATE STATISTICS dbo.YourBadTable WITH FULLSCAN
Depois disso, você pode dar um chute no seu servidor para jogar fora todos os planos antigos.
DBCC FREEPROCCACHE
Se você deseja limpar todos os caches, execute o seguinte:
DBCC FREESYSTEMCACHE ('ALL')
Isso limpará todos os caches, não apenas o cache do plano. Eu normalmente alertaria para usar isso em um servidor de produção na fase de produção. Mas como seu servidor não funciona atualmente, você não pode prejudicá-lo demais. Pode ficar lento por alguns segundos, talvez de 1 a 2 minutos, pois ele precisa reconstruir todos os caches, mas depois disso ele deve executar os planos corretos.
Outro motivo pode ser índices totalmente fragmentados. Isso pode ser verificado em todo o servidor usando esta instrução:
SELECT *
FROM sys.dm_db_index_physical_stats (NULL, NULL, NULL, NULL, NULL)
Se a fragmentação for muito alta, talvez seja necessário reorganizá-la (fragmentação <20%) ou reconstruí-la totalmente (> 20%). Isso pode levar mais pressão ao seu disco e causar problemas. Por outro lado, se os índices forem tão ruins, provavelmente ajudaria no final mais do que prejudica.
Além desses dois motivos, ainda pode haver um terceiro problema
Talvez o servidor esteja configurado provavelmente, você não alterou nenhum código neste momento, apenas adicionou algumas linhas. Todas as estatísticas são atualizadas e todos os caches são reconstruídos. Todos os seus índices são reorganizados da maneira que você precisa, mas ainda assim - nada funciona. Pode ser que você tenha atingido o limite de memória disponível em seus processos. Talvez você precise de mais. Você pode simplesmente verificar se existe algum processo que tente obter mais memória do que você possui.
Você pode verificar isso usando este comando:
SELECT * FROM sys.dm_exec_query_memory_grants
Ele fornecerá uma lista de todas as sessões que consumem memória. Pode haver alguma consulta que ainda esteja aguardando para obter memória. Essas consultas podem ser facilmente filtradas. Todas as sessões onde granted_memory_kb IS NULL. São sessões que solicitaram memória, mas não a obtêm. Outra coisa pode ser uma memória concedida que pode estar muito baixa. Você pode comparar as colunas requested_memory_kbcom granted_memory_kb. Solicitado mostra quanta memória o processo precisa executar ideal, enquanto concedido mostra a memória que está habilitada para o processo. Se um processo precisar de 2 GB para ser executado, mas obtiver apenas 2 MB ... você poderá obtê-lo por conta própria. ;-)
Outra maneira é verificar o RESSOURCE_SEMAPHORE:
SELECT * FROM sys.dm_exec_query_resource_semaphore
Você pode dar uma olhada no waiter_counte no grantee_count. Se o garçom estiver acima de 0, você pressionará sua memória, o que pode causar trocas e causar a pressão do disco vista por você no perfmon.