Eu tenho uma tabela com 490 M de linhas e 55 GB de espaço de tabela, ou seja, cerca de 167 bytes por linha. A tabela tem três colunas: a VARCHAR(100)
, a DATETIME2(0)
e a SMALLINT
. O comprimento médio do texto no VARCHAR
campo é de cerca de 21,5, portanto, os dados brutos devem ter cerca de 32 bytes por linha: 22+2 para o VARCHAR
, 6 para o DATETIME2
e 2 para o inteiro de 16 bits.
Observe que o espaço acima é apenas para dados, não para índices. Estou usando o valor informado em Propriedades | Armazenamento | Geral | Espaço de dados.
Claro que deve haver alguma sobrecarga, mas 135 bytes por linha parece muito, especialmente para uma tabela grande. Por que isso pode ser? Alguém mais viu multiplicadores semelhantes? Que fatores podem influenciar a quantidade de espaço extra necessária?
Para comparação, tentei criar uma tabela com dois INT
campos e 1 milhão de linhas. O espaço de dados necessário foi de 16,4 MB: 17 bytes por linha, em comparação com 8 bytes de dados brutos. Outra tabela de teste com um INT
e um VARCHAR(100)
preenchida com o mesmo texto da tabela real usa 39 bytes por linha (44 K linhas), onde eu esperaria 28 mais um pouco.
Portanto, a tabela de produção tem consideravelmente mais sobrecarga. É porque é maior? Eu esperaria que os tamanhos dos índices fossem aproximadamente N * log(N), mas não vejo por que o espaço necessário para os dados reais não é linear.
Agradecemos antecipadamente por quaisquer ponteiros!
EDITAR:
Todos os campos listados são NOT NULL
. A tabela real tem um PK agrupado no VARCHAR
campo e no DATETIME2
campo, nessa ordem. Para os dois testes, o primeiro INT
foi o PK (agrupado).
Se for importante: a tabela é um registro dos resultados do ping. Os campos são URL, data/hora do ping e latência em milissegundos. Os dados são constantemente anexados e nunca atualizados, mas os dados são excluídos periodicamente para reduzi-los a apenas alguns registros por hora por URL.
EDITAR:
Uma resposta muito interessante aqui sugere que, para um índice com muita leitura e escrita, a reconstrução pode não ser benéfica. No meu caso, o espaço consumido é uma preocupação, mas se o desempenho de gravação for mais importante, pode ser melhor usar índices flácidos.
Após discussões nos comentários sobre a pergunta original, parece que, neste caso, o espaço perdido é causado pela escolha da chave agrupada, que levou a uma fragmentação massiva.
Sempre vale a pena verificar o estado de fragmentação via sys.dm_db_index_physical_stats nessas situações.
Edit: Seguindo a atualização nos comentários
A densidade média da página (antes da reconstrução do índice agrupado) foi de 24%, o que se encaixa perfeitamente com a pergunta original. As páginas estavam apenas 1/4 cheias, então o tamanho total era 4x o tamanho dos dados brutos.
As estruturas em disco têm sobrecarga:
Pegando colunas int de 2 x 4 bytes, você tem
Uau 17 bytes!
Você pode fazer o mesmo para sua segunda tabela de teste, que tem mais sobrecarga como a original:
Por que a diferença? Além disso (não vou vincular a estes)
@updateusage = 'true'
Veja isto: SQL Server: Como criar uma tabela que ocupa uma página de 8 KB?
De SO:
Os tipos de dados mudaram ao longo do tempo? As colunas de comprimento variável foram removidas? Os índices foram desfragmentados com frequência, mas nunca reconstruídos? Muitas linhas foram excluídas ou muitas colunas de comprimento variável foram atualizadas significativamente?