Estou tentando escrever um plug-in munin para representar graficamente os tamanhos do banco de dados. Juntamente com o uso pg_database_size
, também quero representar graficamente seus componentes.
Até agora, cheguei ao seguinte:
SELECT
SUM(pg_relation_size(oid, 'main')) AS main_size,
SUM(pg_relation_size(oid, 'vm')) AS vm_size,
SUM(pg_relation_size(oid, 'fsm')) AS fsm_size,
SUM(
CASE reltoastrelid
WHEN 0 THEN 0
ELSE pg_total_relation_size(reltoastrelid)
END
) AS toast_size,
SUM(pg_indexes_size(oid)) AS indexes_size
FROM pg_class
WHERE reltype != 0 -- 0=indices, covered by pg_indexes_size
No entanto, somar esses 5 valores me retorna algo que não é o mesmo que o resultado de pg_database_size
. A diferença parece ser menos significativa para bancos de dados maiores.
Exemplo em um banco de dados maior:
┌──────────┬────────┬─────────┬─────────┬──────────┬───────────────┬──────────────────┬─────────┐
│ main │ vm │ fsm │ toast │ indexes │ sum_of_values │ pg_database_size │ diff │
├──────────┼────────┼─────────┼─────────┼──────────┼───────────────┼──────────────────┼─────────┤
│ 72441856 │ 753664 │ 2392064 │ 4677632 │ 41377792 │ 116 MB │ 111 MB │ 5222 kB │
└──────────┴────────┴─────────┴─────────┴──────────┴───────────────┴──────────────────┴─────────┘
(1 row)
Exemplo em um banco de dados menor:
┌─────────┬────────┬─────────┬────────┬─────────┬───────────────┬──────────────────┬─────────┐
│ main │ vm │ fsm │ toast │ indexes │ sum_of_values │ pg_database_size │ diff │
├─────────┼────────┼─────────┼────────┼─────────┼───────────────┼──────────────────┼─────────┤
│ 2809856 │ 385024 │ 1351680 │ 557056 │ 2924544 │ 7840 kB │ 6642 kB │ 1198 kB │
└─────────┴────────┴─────────┴────────┴─────────┴───────────────┴──────────────────┴─────────┘
(1 row)
o que estou perdendo?
Talvez relacionado, talvez não: estou chocado ao ver o tamanho do índice. Eles são ENORMES. Algo na minha consulta está errado?
Aqui está um script que usei para inspecionar os diferentes valores:
SELECT
SUM(pg_relation_size(oid, 'main')) AS main,
SUM(pg_relation_size(oid, 'vm')) AS vm,
SUM(pg_relation_size(oid, 'fsm')) AS fsm,
SUM(
CASE reltoastrelid
WHEN 0 THEN 0
ELSE pg_total_relation_size(reltoastrelid)
END
) AS toast,
SUM(pg_indexes_size(oid)) AS indexes,
pg_size_pretty(
SUM(pg_relation_size(oid, 'main'))::bigint +
SUM(pg_relation_size(oid, 'vm'))::bigint +
SUM(pg_relation_size(oid, 'fsm'))::bigint +
SUM(pg_indexes_size(oid))::bigint +
SUM(
CASE reltoastrelid
WHEN 0 THEN 0
ELSE pg_total_relation_size(reltoastrelid)
END
)::bigint
) AS sum_of_values,
pg_size_pretty(pg_database_size(current_database())) AS pg_database_size,
pg_size_pretty(
SUM(pg_relation_size(oid, 'main'))::bigint +
SUM(pg_relation_size(oid, 'vm'))::bigint +
SUM(pg_relation_size(oid, 'fsm'))::bigint +
SUM(pg_indexes_size(oid))::bigint +
SUM(
CASE reltoastrelid
WHEN 0 THEN 0
ELSE pg_total_relation_size(reltoastrelid)
END
)::bigint - pg_database_size(current_database())::bigint
) AS diff
FROM pg_class
WHERE reltype != 0;
Você está contando as mesas de torradas duas vezes. Uma vez sob seu proprietário, como
pg_total_relation_size(reltoastrelid)
, e novamente sob sua própria entrada em pg_class. Você deve usar relkind, não reltype, para filtrar o que deseja.Além disso, tentar microgerenciar seu RDBMS nessa extensão raramente compensa.
pg_database_size()
essencialmente consulta o sistema de arquivos para o tamanho de$PGDATA/base/oid-of-database
(o diretório de dados por banco de dados), mais o tamanho de cada diretório em espaços de tabela não padrão adicionados comCREATE TABLESPACE
.Se houver arquivos nesses diretórios que não pertençam a nenhuma relação, eles também serão contados. Olhando para um banco de dados aleatório, posso ver
pg_internal.init
,PG_VERSION
,pg_filenode.map
que estão nesse caso. Eles somam o tamanho do diretório e não serão contados em nenhuma consulta de controle.Arquivos de dados perdidos também podem existir. Consulte Como recuperar o espaço ocupado por um índice que foi parcialmente construído e encerrado por uma queda de energia para obter um exemplo concreto. Eles também não podem ser encontrados consultando
pg_class
, por definição, e são contados no tamanho do banco de dados no disco.Com relação à consulta, apenas para fins de obter a soma dos tamanhos dos objetos, sugiro uma versão mais simples:
Observe que as relações compartilhadas são removidas desta consulta (
not relisshared
). Os objetos compartilhados são visíveis de todos os bancos de dados e não pertencem a nenhum diretório do banco de dados, eles estão em$PGDATA/global
. Uma das tabelas compartilhadas que se espera ter um tamanho significativo épg_shdepend
. Negligenciar isso em sua consulta original faz com que seja superestimado (além do comentário de @jjanes sobre tabelas de torradas).