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]CHAR
vez 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_spaceused
executado 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.objects
e sys.dm_db_partition_stats
usadas 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:
- Aquilo que não está alocado para nada (isso é mostrado no primeiro conjunto de resultados
sp_spaceused
sem nenhum objeto especificado)
- O que é alocado para um objeto (reservado), mas não é usado atualmente (isso é mostrado na contagem "não utilizada" na
sp_spaceused
saída de.
- 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 ( TEXT
colunas,[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.