Eu tenho 2 tabelas com os esquemas abaixo com igual número de linhas. Quando executo o SELECT relname, relpages FROM pg_class ORDER BY relpages DESC
comando, eles aparecem como 23 GB cada, embora os tipos de dados (número total de bytes) para os dois esquemas resultem em tamanhos diferentes. Qual é a melhor maneira de descobrir quanto espaço eu economizaria combinando tabelas? Além disso, existe alguma maneira de determinar quanto espaço cada linha está realmente ocupando?
Table "public.table1"
Column | Type | Modifiers
--------------+--------------------------+-----------------------------------------------------
field1 | smallint |
field2 | smallint |
field3 | integer |
field4 | smallint |
timestamp | timestamp with time zone |
user_id | integer |
status | boolean |
id | integer | not null default
Table "public.table2"
Column | Type | Modifiers
----------------+--------------------------+----------------------------------------------------
user_id | integer |
begin_timestamp | timestamp with time zone |
end_timestamp | timestamp with time zone |
field | smallint | not null
id | integer | not null default
Como a tabela combinada resultante teria linhas não utilizadas para registros de cada tabela respectiva, é provável que você não ganhe espaço, mas o perca.
Mais importante do que isso, eu desencorajaria fortemente tomar uma decisão de arquitetura dessa natureza por motivos de espaço em disco. Os discos são baratos - um aplicativo bem projetado e funcional não é. Se houver um problema de desempenho em tempo de execução (ou seja, todos os 46 GB estão sendo carregados na memória/espaço de troca), você pode ter um problema de otimização e ajuste em suas mãos.
Uma resposta razoável para isso deve IMHO perguntar (ou pelo menos sugerir) a pergunta: Por que as tabelas foram divididas para começar? (Mais importante: ainda se aplica?)
O caso geral: não conheço os detalhes de como o mecanismo de banco de dados postgres funciona, mas o limite inferior do espaço em disco salvo pode não ser maior que o tamanho das colunas removidas + índices de variáveis duplicadas + um pouco de dados de limpeza
O limite superior também é muito pequeno, então provavelmente não valerá a pena; pode até ser que eles tenham sido particionados por questões de desempenho - porque algumas colunas seriam acessadas (lidas ou mesmo atualizadas) com mais frequência e, como tal, poderiam ser reduzidas (menos colunas) para torná-lo mais rápido. (Com alguma penalidade por acessar colunas de ambos ao mesmo tempo.)
O caso específico: parece que há muitos campos redundantes entre eles. user_id, por exemplo, não precisaria estar lá duas vezes. timestamps de início/fim/X talvez possam ser reduzidos para dois ou um. Portanto, pode haver uma pequena economia com isso, dependendo dos requisitos do aplicativo. Mais uma vez, tente descobrir por que eles fizeram isso para começar.
No geral, porém, concordo com Bryan Agee; o espaço em disco provavelmente não deve ser sua preocupação em nada grande o suficiente para executar o postgres para começar. Especialmente se você for pago pelo tempo gasto em "consertar" isso, esse custo provavelmente excederá o custo do disco maior por si só.
Espaço por linha: não sou muito versado em detalhes do postgres, então alguém que saiba deve ser capaz de corrigir qualquer coisa errada. Por exemplo, existe uma maneira de perguntar ao postgres quanto espaço aquela linha específica está realmente ocupando; Eu não conheço nenhum. O que estou escrevendo é basicamente a teoria por trás do armazenamento de banco de dados como (acredito) comumente feito hoje.
Cada campo tem um bit (em um byte próprio, ou em um bitset comum para toda a linha) que diz se o valor é nulo ou não. Se for um valor nulo, não há mais nada armazenado. Depois, há um byte de comprimento - a menos que isso esteja implícito nos tipos de dados de largura fixa. Depois, há os dados em si.
Assim, uma linha de um int (mesmo de 64 bits) e três valores nulos pode ocupar apenas 3 bytes. (Para valores <127, armazenando size=1 e o byte.) Mais índices e vários outros metadados de limpeza . Mais uma vez, não sei até onde o postgres vai nesse sentido. E todos esses fatores juntos tenderão a tornar "quanto esta linha ocupa" uma pergunta com uma resposta inútil.
AFAIK postgres também opera com "páginas" - blocos de espaço nos quais uma linha não pode ser armazenada além dos limites. Portanto, registros maiores podem acabar "simplesmente não cabendo" em uma página e, portanto, precisam ser colocados em outra/nova página.