Tamanho do banco de dados - MDF muito grande?

10

Estou mantendo um banco de dados do SQL Server 2005 que hospeda aproximadamente 2,9 TB de dados (2 x 1,45 TB - eu tenho um esquema RAW e um esquema ANALYSIS, basicamente duas cópias dos dados ingeridos). O modelo de recuperação é SIMPLES e .ldfestá em 6 GB.

Por qualquer motivo, o .mdfé 7.5Tb. Agora, existem apenas 2-3 colunas adicionais nas tabelas ANALYSIS e poucas NVARCHAR(MAX)colunas que, pelo que eu (possa ter entendido por engano - corrija-me se estiver errado), podem estar causando alocação de espaço adicional. Isso depois de diminuir o banco de dados agora - estava em ~ 9 TB antes disso. Alguma ideia?

E, por favor, deixe-me saber se você tiver perguntas adicionais - sou muito novo nos esforços de administração e otimização de banco de dados (geralmente não faço esse lado do trabalho :)).

Muito Obrigado!

Andrija

Andrija_Bgd
fonte
Obrigado Marc - de alguma forma eu posso mudar essa pergunta para lá ou preciso postar novamente?
Felicidades - como você provavelmente pode adivinhar, eu sou novo aqui :)

Respostas:

11

Nas suas estimativas de tamanho, você levou em consideração a quantidade de espaço ocupado pelos índices? Além disso, se você tiver campos de texto definidos como vários bytes (em N[VAR]CHARvez de [VAR]CHAR) e os arquivos de entrada forem UTF-8 ou um byte simples por caractere, isso aumentará seus requisitos de armazenamento em até um fator de dois. Além disso, lembre-se de que, se você tiver uma chave / índice em cluster em uma tabela, o tamanho disso afeta todos os outros índices na tabela, porque eles incluem o valor da chave em cluster para cada linha (para dar um exemplo extremo se uma tabela tiver um NCHAR (10 ) onde uma INT faria e essa é sua chave / índice clusterizado, você não está apenas usando 16 bytes adicionais por linha nas páginas de dados, mas também desperdiça 16 bytes por linha em todos os outros índices dessa tabela ) .

Além disso, algum espaço será alocado, mas não utilizado, porque o mecanismo do DB deixou algum espaço alocado após a exclusão, para que possa ser usado novamente rapidamente para novos dados nessa tabela ou porque o padrão de inserções e exclusões deixou muitas páginas apenas em parte cheio.

Você pode correr:

SELECT o.name
     , SUM(ps.reserved_page_count)/128.0 AS ReservedMB
     , SUM(ps.used_page_count)/128.0 AS UsedMB
     , SUM(ps.reserved_page_count-ps.used_page_count)/128.0 AS DiffMB
FROM sys.objects o  
JOIN sys.dm_db_partition_stats ps ON o.object_id = ps.object_id  
WHERE OBJECTPROPERTYEX(o.object_id, 'IsMSShipped') = 0  
GROUP BY o.name  
ORDER BY SUM(ps.reserved_page_count) DESC

para ver rapidamente quais tabelas estão ocupando espaço.

Também EXEC sp_spaceusedexecutado nesse banco de dados retornará dois conjuntos de resultados. O primeiro lista o espaço total alocado no sistema de arquivos para os arquivos de dados e quanto disso não está alocado, o segundo lista o quanto do espaço alocado é usado para páginas de dados, páginas de índice ou não está sendo usado no momento.

sp_spaceused retornará o espaço usado por um determinado objeto também, para que você possa fazer um loop para criar uma tabela para análise:

-- TEMP TABLES FOR ANALYSIS
CREATE TABLE #tTables (sName NVARCHAR(MAX), iRows BIGINT, iReservedKB BIGINT, iDataKB BIGINT, iIndexKB BIGINT, iUnusedKB BIGINT)
CREATE TABLE #tTmp (sName NVARCHAR(MAX), iRows BIGINT, sReservedKB NVARCHAR(MAX), sDataKB NVARCHAR(MAX), sIndexKB NVARCHAR(MAX), sUnusedKB NVARCHAR(MAX))
-- COLLECT SPACE USE PER TABLE
EXEC sp_msforeachtable 'INSERT #tTmp EXEC sp_spaceused [?];'
-- CONVERT NUMBER-AS-TEXT COLUMNS TO NUMBER TYPES FOR EASIER ANALYSIS
INSERT #tTables SELECT sName, iRows
                     , CAST(REPLACE(sReservedKB, ' KB', '') AS BIGINT)
                     , CAST(REPLACE(sDataKB    , ' KB', '') AS BIGINT)
                     , CAST(REPLACE(sIndexKB   , ' KB', '') AS BIGINT)
                     , CAST(REPLACE(sUnusedKB  , ' KB', '') AS BIGINT) 
                FROM #tTmp
DROP TABLE #tTmp 
-- DO SOME ANALYSIS 
SELECT sName='TOTALS', iRows=SUM(iRows), iReservedKB=SUM(iReservedKB), iDataKB=SUM(iDataKB),  iIndexKB=SUM(iIndexKB), iUnusedKB=SUM(iUnusedKB) FROM #tTables ORDER BY sName
SELECT * FROM #tTables ORDER BY iReservedKB DESC
-- CLEAN UP
DROP TABLE #tTables

O código acima produzirá todos os tamanhos de tabela em uma lista, além de uma única linha para os totais. Se necessário, você pode usar as várias visualizações do sistema (como sys.objectse sys.dm_db_partition_statsusadas na primeira consulta acima, consulte http://technet.microsoft.com/en-us/library/ms177862.aspx para obter mais detalhes) para obter mais detalhes, como o espaço usado por cada índice.


Existem três classes de espaço não utilizado em um arquivo de dados:

  1. Aquilo que não está alocado para nada (isso é mostrado no primeiro conjunto de resultados sp_spaceusedsem nenhum objeto especificado)
  2. O que é alocado para um objeto (reservado), mas não é usado atualmente (isso é mostrado na contagem "não utilizada" na sp_spaceusedsaída de.
  3. Bloqueado em páginas usadas parcialmente (isso parecerá ser usado, pois tudo está alocado em blocos de página única, com uma página com 8.192 bytes). Isso é mais difícil de detectar / calcular. Isso se deve a uma mistura de dois fatores:
    • Dividir páginas. À medida que os dados são adicionados, muitas vezes você acaba com páginas parcialmente vazias (o mecanismo de armazenamento sempre pode normalizar o conteúdo da página, mas isso seria muito ineficiente) e, à medida que as linhas são excluídas, o conteúdo da página não é compactado automaticamente (novamente, mas sim o extra A carga de E / S geralmente está longe de valer a pena).
    • O mecanismo de armazenamento não dividirá uma linha em várias páginas (junto com o tamanho da página de onde vem o limite de 8.192 bytes por linha). Se suas linhas tiverem tamanho fixo e ocuparem 1.100 bytes cada, você "desperdiçará" pelo menos 492 bytes de cada bloco de dados alocado para essa tabela (7 linhas ocupam 7.700 bytes e um oitavo não cabe, portanto os bytes restantes serão ganhos " não ser usado). Quanto mais largas as linhas, pior pode ser. Tabelas / índices com linhas de comprimento variável (que são muito mais comuns que as de comprimento completamente fixo) geralmente são melhores (mas são menos fáceis de calcular o assunto).
      Outra ressalva aqui são os objetos grandes ( TEXTcolunas,[N]VARCHAR(MAX) valores acima de um determinado tamanho e assim por diante), à ​​medida que são colocados fora da página, apenas colocando 8 bytes nos dados da linha principal para manter um ponteiro para os dados em outro lugar) para que você possa quebrar o limite de 8.192 bytes por linha.

tl; dr: A estimativa do tamanho esperado do banco de dados pode ser muito mais envolvente do que é natural supor inicialmente.

David Spillett
fonte
David - muito obrigado pela resposta detalhada! Estou analisando o banco de dados agora e as respostas de você e de Kenneth foram de imensa ajuda na minha compreensão dos fatores que influenciam o tamanho do banco de dados. Estou sempre preocupado com a eficiência (tanto no que diz respeito à ingestão e uso de dados) quanto às informações que vocês forneceram foram inestimáveis!
precisa saber é o seguinte
6

Tente executar sp_spaceusedno seu banco de dados. Como exemplo, ele retorna:

reserved           data               index_size         unused
------------------ ------------------ ------------------ ------------------
6032 KB            2624 KB            1664 KB            1744 KB

Para executá-lo no banco de dados, basta USEexecutar o banco de dados sp_spaceused.

Se ele ainda mostrar uma grande quantidade de espaço não utilizado, você pode tentar o psiquiatra novamente. Às vezes, acho que são necessárias várias tentativas. Às vezes, também acho que funciona melhor reduzir o arquivo individual em vez do banco de dados como um todo. No entanto, o que você pode descobrir é que você possui 2,9 TB de dados e outros 4 + TB de índices. Nesse caso, o 7,5 TB é bastante razoável. Se você quiser ter uma idéia da quantidade de espaço (dados e índice) de cada tabela, também poderá executar sp_spaceusedno nível da tabela. Você pode executá-lo em todas as tabelas no banco de dados usando o seguinte comando:

EXEC sp_msforeachtable 'EXEC sp_spaceused [?];'

Embora o aviso justo sp_msforeachtable seja indocumentado, sem suporte e conhecido por perder tabelas. Por outro lado, tive muita sorte comigo mesmo.

Tudo isso dito seu banco de dados deve ter uma certa porcentagem de espaço livre, dependendo do seu crescimento esperado. Basicamente, você quer ter espaço para um período de 6 meses a alguns anos de crescimento. Além disso, você desejará verificar suas autogrowthconfigurações para garantir que elas sejam apropriadas à sua situação. Dado o tamanho do seu banco de dados, você NÃO deseja usar% autogrowth.

Kenneth Fisher
fonte
Obrigado! Eu usei o sp_spaceused e parece que os dados reais ocupam a quantidade indicada de espaço, por mais estranho que isso possa parecer, dado o tamanho real dos arquivos simples que foram carregados ... Os índices são pequenos criei outros adicionais, pois seriam mais um obstáculo do que ajuda no meu caso), então acho que são apenas as tabelas reais que são grandes ... Agradecemos um milhão pela ajuda!
Andrija_Bgd
Os bancos de dados ocupam mais espaço que os arquivos simples. Há uma certa sobrecarga para as estruturas de linha e tabela e uma certa quantidade de desperdício devido à estrutura da página.
Kenneth Fisher
-1

Usando o SQL Management Studio, 1.Clique com o botão direito do mouse no banco de dados e depois 2.Clique em Tarefas-> Reduzir -> Arquivos

Você verá uma caixa de diálogo que mostra: a. Espaço atualmente alocado b. Espaço livre disponível + (% gratuito)

Se o seu% gratuito estiver acima de 50%, considere reduzir o arquivo. Eu já vi esse sucesso em até 90%. Se eu decidir diminuir o arquivo, normalmente o defino como 2 ou 3 GB a mais do que o espaço alocado atual. A maioria dos meus bancos de dados tem menos de 50gigs. Portanto, se você tiver um arquivo muito maior, poderá torná-lo 10 GB maior. Normalmente, só me preocupo em encolher se for mover o banco de dados para outro servidor. Você pode ler tudo sobre encolher problemas em qualquer página sql.

Clark Vera
fonte