O cálculo do tamanho da linha é muito mais complexo do que isso.
O armazenamento é normalmente particionado em páginas de dados de 8 kB . Há uma pequena sobrecarga fixa por página, possíveis restos não grandes o suficiente para caber em outra tupla e, mais importante, linhas mortas ou uma porcentagem inicialmente reservada com o
FILLFACTOR
contexto. E há ainda mais sobrecarga por linha (tupla):um identificador de item de 4 bytes no início da página, o
HeapTupleHeader
de 23 bytes e preenchimento de alinhamento . O início do cabeçalho da tupla, bem como o início dos dados da tupla, são alinhados em um múltiplo de MAXALIGN
, que é de 8 bytes em uma máquina típica de 64 bits. Alguns tipos de dados requerem alinhamento com o próximo múltiplo de 2, 4 ou 8 bytes. Citando o manual na tabela do sistema
pg_tpye
:
typalign
é o alinhamento necessário ao armazenar um valor desse tipo. Ele se aplica ao armazenamento em disco, bem como à maioria das representações do valor dentro do PostgreSQL. Quando vários valores são armazenados consecutivamente, como na representação de uma linha completa em disco, o preenchimento é inserido antes de um dado desse tipo para que ele comece no limite especificado. A referência de alinhamento é o início do primeiro dado na sequência.
Os valores possíveis são:
c
=char
alinhamento, ou seja, nenhum alinhamento necessário.
s
=short
alinhamento (2 bytes na maioria das máquinas).
i
=int
alinhamento (4 bytes na maioria das máquinas).
d
=double
alinhamento (8 bytes em muitas máquinas, mas não em todas).
Leia sobre o básico no manual aqui.
Seu exemplo
Isso resulta em 4 bytes de preenchimento após seus 3
integer
colunas, porque o timestamp
coluna requer double
alinhamento e precisa começar no próximo múltiplo de 8 bytes. Assim, uma linha ocupa:
23 -- heaptupleheader
+ 1 -- padding or NULL bitmap
+ 12 -- 3 * integer (no alignment padding here)
+ 4 -- padding after 3rd integer
+ 8 -- timestamp
+ 0 -- no padding since tuple ends at multiple of MAXALIGN
Mais identificador de item por tupla no cabeçalho da página (conforme indicado por @A.H. no comentário):
+ 4 -- item identifier in page header
------
= 52 bytes
Assim, chegamos aos 52 bytes observados .
O cálculo
pg_relation_size(tbl) / count(*)
é uma estimativa pessimista. pg_relation_size(tbl)
inclui bloat (linhas mortas) e espaço reservado por fillfactor
, bem como sobrecarga por página de dados e por tabela. (E nós nem mencionamos compressão por muito tempo varlena
dados nas tabelas TOAST, pois não se aplica aqui.) Você pode instalar o módulo adicional pgstattuple e chamar
SELECT * FROM pgstattuple('tbl_name');
para obter mais informações sobre o tamanho da tabela e da tupla. Relacionado:
- Tamanho da tabela com layout de página
- Calculando e economizando espaço no PostgreSQL