Fragmentação de arquivo físico do Banco de Dados SQL

19

Eu sei que existem realmente três tipos de fragmentação que eu preciso me preocupar como DBA:

  1. Fragmentação de índice nos arquivos de dados SQL, incluindo fragmentação de índice (tabela) em cluster. Identifique isso usando DBCC SHOWCONTIG (no SQL 2000) ou sys.dm_ db_ index_ physical_ stats (em 2005+).

  2. Fragmentação VLF dentro dos arquivos de log SQL. Execute DBCC LOGINFO para ver quantos VLFs existem em cada um dos seus arquivos de log SQL.

  3. Fragmentação física dos arquivos do banco de dados no disco rígido. Faça o diagnóstico usando o utilitário "Desfragmentador de disco" no Windows. (inspirado por este excelente post no blog )

Muita atenção é dada à fragmentação do índice (veja esta excelente resposta do Serverfault de Paul Randall), portanto esse não é o foco da minha pergunta.

Sei que posso impedir a fragmentação física (e a fragmentação VLF) quando o banco de dados é originalmente criado, planejando um arquivo de dados e tamanho de log razoáveis, porque essa fragmentação ocorre com maior frequência devido a crescimentos e encolhimentos frequentes, mas tenho algumas dúvidas sobre como corrigir fragmentação física, uma vez identificado:

  • Antes de tudo, a fragmentação física é relevante em uma SAN corporativa? Posso / devo usar o Desfragmentador do Windows em uma unidade SAN ou a equipe da SAN deve usar utilitários de desfragmentação internos? A análise de fragmentação que recebo da ferramenta Windows é precisa quando executada em uma unidade SAN?

  • Quão grande é a fragmentação física no desempenho do SQL? (Vamos assumir uma matriz de unidades internas, enquanto se aguarda o resultado da pergunta anterior.) É um negócio MAIOR do que a fragmentação interna do índice? Ou é realmente o mesmo tipo de problema (a unidade precisa fazer leituras aleatórias em vez de sequenciais)

  • A desfragmentação (ou a reconstrução) dos índices é uma perda de tempo se a unidade estiver fisicamente fragmentada? Preciso corrigir um antes de abordar o outro?

  • Qual é a melhor maneira de corrigir a fragmentação de arquivo físico em uma caixa SQL de produção? Sei que posso desativar os serviços SQL e executar o Windows Defrag, mas também ouvi falar de uma técnica em que você faz um backup completo, descarta o banco de dados e depois restaura o backup para uma unidade vazia. Esta última técnica é recomendada? A restauração de um backup como esse também cria índices do zero, eliminando a fragmentação interna do índice? Ou simplesmente retorna a ordem das páginas para a mesma de quando o backup foi realizado? (Estamos usando backups do Quest Lightspeed com compactação, se isso importa.)

ATUALIZAÇÃO : Boas respostas até agora sobre a desfragmentação de unidades SAN (NÃO) e se a desfragmentação do índice ainda vale a pena em unidades fisicamente fragmentadas (SIM).

Alguém mais gostaria de avaliar os melhores métodos para fazer a desfragmentação? Ou uma estimativa do tempo que você esperaria para desfragmentar uma grande unidade fragmentada, digamos 500 GB ou mais? Relevante, obviamente, porque é nessa hora que meu servidor SQL estará inoperante!

Além disso, se alguém tiver informações anedóticas sobre as melhorias de desempenho do SQL que você fez ao corrigir a fragmentação física, isso também seria ótimo. O post de Mike fala sobre descobrir o problema, mas não é específico sobre o tipo de melhoria que ele fez.

BradC
fonte

Respostas:

9

Acho que este artigo fornece uma excelente visão geral da desfragmentação de unidades SAN

http://www.las-solanas.com/storage_virtualization/san_volume_defragmentation.php

O ponto básico é que a desfragmentação não é recomendada no armazenamento da SAN, pois é difícil correlacionar a localização física dos blocos no disco quando a localização foi virtualizada pela SAN ao apresentar o LUN.

Se você estava usando mapeamentos de dispositivos RAW ou tem acesso direto a um conjunto RAID que é o LUN com o qual está trabalhando, eu poderia ver a desfragmentação tendo um efeito positivo, mas se você receber um LUN "virtual" de um RAID compartilhado, 5 conjunto, não.

Kevin Kuphal
fonte
Excelente artigo. Bem no ponto em relação às unidades SAN.
24909 BradC
7

Várias partes desta pergunta e resposta:

A fragmentação física de arquivos não é realmente relevante para o armazenamento Enterprise SAN, como Kevin já apontou - portanto, nada a acrescentar. Realmente se resume ao subsistema de E / S e a probabilidade de você poder fazer com que as unidades passem de E / Ss mais aleatórias ao executar uma varredura para E / Ss mais sequenciais ao executar uma varredura. para o DAS, é mais provável que você faça, para uma SAN complexa fatia-e-dado, provavelmente não.

Desfragmentação no nível do sistema de arquivos - faça-o apenas com o SQL desligado. Eu nunca tive problemas aqui (como nunca realizei uma desfragmentação on-line de arquivos de banco de dados SQL), mas ouvi muitas evidências anedóticas de clientes e clientes de problemas estranhos de corrupção. A sabedoria geral não é fazê-lo com o SQL online.

A fragmentação do índice é completamente ortogonal à fragmentação do arquivo. O SQL Server não tem idéia da fragmentação de arquivos - muitas camadas de virtualização intermediárias para ter alguma esperança de descobrir as geometrias reais do subsistema de E / S. Fragmentação de índice, no entanto, o SQL sabe tudo sobre. Sem me repetir muito da resposta que você já referenciou, a fragmentação do índice impedirá o SQL de executar uma leitura eficiente do alcance da leitura, independentemente de quão fragmentados (ou não) os arquivos estejam no nível do sistema de arquivos. Então, absolutamente, você deve atenuar a fragmentação do índice se estiver vendo um desempenho degradante da consulta.

Você não precisa fazer isso em nenhuma ordem específica, embora, se você cuidar da fragmentação do sistema de arquivos e depois reconstruir todos os seus índices e causar mais fragmentação do sistema de arquivos aumentando vários arquivos em um volume desfragmentado, provavelmente vai ser marcado. Isso causará problemas de desempenho? Como discutido acima, depende :-D

Espero que isto ajude!

Paul Randal
fonte
Ah, então a fragmentação interna do índice realmente altera o comportamento do otimizador, para favorecer varreduras completas em vez das buscas apropriadas pelo intervalo de índices?
24909 BradC
Não. O otimizador não tem conhecimento de como os dados são armazenados no disco, além do fato de existirem índices, seu tamanho e estatísticas de distribuição do valor da coluna. É o mecanismo de armazenamento que conduz o readahead e altera os tamanhos de E / S individuais com base na fragmentação lógica do que está sendo verificado.
Paul Randal
3

Qual é a melhor maneira de corrigir a fragmentação de arquivo físico em uma caixa SQL de produção?

Eu executo o contigo do SYSINTERNALS nos meus arquivos de banco de dados.

Consulte http://technet.microsoft.com/en-us/sysinternals/bb897428.aspx

Vincent Buck
fonte
Parece interessante. Presumo que, uma vez que ele usa as APIs de desfragmentação do Windows, os serviços SQL precisariam estar desativados? Ou isso seria executado enquanto o servidor / banco de dados estiver online?
BradC
Eu usei com sucesso em bancos de dados online do MSSQL Server. Mas, sem dúvida, aqueles eram de baixo tráfego e bancos de dados pequenos (menos de 10 Gb)
Vincent Buck
Essa é uma ótima ferramenta! Eu acho que suas aplicações para bancos de dados são bastante limitadas, como mencionado por outras pessoas, mas eu adoro isso para outros tipos de unidades. O modo de análise -a é seguro enquanto as coisas estão em execução. Eu não me sentiria seguro executando-o em uma unidade pertencente a um SQL Server ativo.
Kendra
2

Eu recomendaria dimensionar o banco de dados adequadamente, desligando o servidor sql, copie o arquivo de banco de dados para outra matriz de disco e copie-o novamente para desfragmentá-lo. Muito mais rápido do que usar o Windows desfragmentar na minha experiência.


fonte
1

Tentei desfragmentar os discos físicos em uma solução scsi uma vez, mas obtive pouco ou nenhum aumento de desempenho. A lição que aprendi é que, se você experimenta um desempenho lento devido ao sistema de disco, ele não tem nada a ver com a fragmentação, na medida em que falamos sobre o arquivo de dados, pois está usando acesso aleatório.

Se seus índices são desfragmentados e as estatísticas são atualizadas (muito importante) e você ainda vê E / S como gargalo, sofre de outras coisas além da fragmentação física. Você já usou mais de 80% da unidade? Você tem unidades suficientes? Suas consultas estão otimizadas o suficiente? Você está fazendo muitas varreduras de tabela ou, pior ainda, muitas pesquisas de índice seguidas de pesquisa de índice em cluster? Veja os planos de consulta e use "definir estatísticas io on" para descobrir o que realmente está acontecendo com sua consulta. (procure um número alto de leituras lógicas ou físicas)

Por favor, deixe-me saber se estou completamente errado.

/ Håkan Winther

Hakan Winther
fonte
Não, você não está errado. Mas tentar fazer algumas melhorias em todo o servidor (se possível) é um pouco mais atraente do que começar a mergulhar nas mais de 150.000 instruções SQL distintas que são executadas durante os trabalhos semanais de análise (não um exagero. Provavelmente um eufemismo)
BradC
Se você tiver esse tipo de situação, recomendo que o Veritas I3 analise seu ambiente para ver de que gargalo você está sofrendo e o que está causando esse gargalo. O Veritas I3 controla todas as instruções, com que frequência elas são chamadas e a que custo. É um excelente software.
Hakan Winther
1

Talvez os índices não estejam otimizados o suficiente para o seu aplicativo e você não tenha o Veritas I3 para otimizar seu banco de dados. Você pode usar uma declaração como esta para encontrar índices ausentes:

       SELECT
      mid.statement,
      mid.equality_columns,
      mid.inequality_columns,
      mid.included_columns,
      migs.user_seeks,
      migs.user_scans,
      migs.last_user_seek,
      migs.avg_user_impact,
      user_scans,
      avg_total_user_cost,
      avg_total_user_cost * avg_user_impact * (user_seeks + user_scans) AS [weight]--, migs.*--, mid.*
   FROM
      sys.dm_db_missing_index_group_stats AS migs
      INNER JOIN sys.dm_db_missing_index_groups AS mig
         ON (migs.group_handle = mig.index_group_handle)
      INNER JOIN sys.dm_db_missing_index_details AS mid
         ON (mig.index_handle = mid.index_handle)
   ORDER BY
      avg_total_user_cost * avg_user_impact * (user_seeks + user_scans) DESC ;

Ou uma declaração como essa para encontrar índices que não são usados ​​nas instruções de seleção e diminui o desempenho de atualização / inserção:

    CREATE PROCEDURE [ADMIN].[spIndexCostBenefit]
    @dbname [nvarchar](75)
WITH EXECUTE AS CALLER
AS
--set @dbname='Chess'
declare @dbid nvarchar(5)
declare @sql nvarchar(2000)
select @dbid = convert(nvarchar(5),db_id(@dbname))

set @sql=N'select ''object'' = t.name,i.name
        ,''user reads'' = iu.user_seeks + iu.user_scans + iu.user_lookups
        ,''system reads'' = iu.system_seeks + iu.system_scans + iu.system_lookups
        ,''user writes'' = iu.user_updates
        ,''system writes'' = iu.system_updates
from '+ @dbname + '.sys.dm_db_index_usage_stats iu
,' + @dbname + '.sys.indexes i
,' + @dbname + '.sys.tables t
where 
    iu.database_id = ' + @dbid + '
and iu.index_id=i.index_id
and iu.object_id=i.object_id
and iu.object_id=t.object_id
AND (iu.user_seeks + iu.user_scans + iu.user_lookups)<iu.user_updates
order by ''user reads'' desc'

exec sp_executesql @sql

set @sql=N'SELECT
   ''object'' = t.name,
   o.index_id,
   ''usage_reads'' = user_seeks + user_scans + user_lookups,
   ''operational_reads'' = range_scan_count + singleton_lookup_count,
   range_scan_count,
   singleton_lookup_count,
   ''usage writes'' = user_updates,
   ''operational_leaf_writes'' = leaf_insert_count + leaf_update_count + leaf_delete_count,
   leaf_insert_count,
   leaf_update_count,
   leaf_delete_count,
   ''operational_leaf_page_splits'' = leaf_allocation_count,
   ''operational_nonleaf_writes'' = nonleaf_insert_count + nonleaf_update_count + nonleaf_delete_count,
   ''operational_nonleaf_page_splits'' = nonleaf_allocation_count
FROM
   ' + @dbname + '.sys.dm_db_index_operational_stats(' + @dbid + ', NULL, NULL, NULL) o,
   ' + @dbname + '.sys.dm_db_index_usage_stats u,
    ' + @dbname + '.sys.tables t
WHERE
   u.object_id = o.object_id
   AND u.index_id = o.index_id
    and u.object_id=t.object_id
ORDER BY
   operational_reads DESC,
   operational_leaf_writes,
   operational_nonleaf_writes'

exec sp_executesql @sql

GO

Eu tenho algumas outras instruções SQL que estou usando ao analisar problemas de desempenho no ambiente de produção, mas acho que essas duas são um bom começo.

(Eu sei, este post é um pouco de tópico, mas achei que você poderia estar interessado, pois tem a ver com estratégia de indexação)

/ Håkan Winther

Hakan Winther
fonte
Excelentes scripts, tenho alguns muito parecidos. Infelizmente, ainda somos 40% do SQL 2000 (incluindo o servidor em questão), que não possui nenhum equivalente a essas DMVs de "índice ausente".
BradC
Entendo, então eu recomendo que você dê uma olhada no Veritas I3. É um excelente produto que você pode usar para ajustar seus bancos de dados, mas não é um software barato.
Hakan Winther