Understanding where pg_toast is coming from
-
27-02-2021 - |
Вопрос
I've got a fair amount of storage in pg_toast
relation | size
----------------------------------+---------
pg_toast.pg_toast_43934449 | 87 GB
pg_toast.pg_toast_43934438 | 64 GB
pg_toast.pg_toast_50877 | 35 GB
pg_toast.pg_toast_16715 | 15 GB
pg_toast.pg_toast_16813 | 13 GB
pg_toast.pg_toast_5706469 | 1335 MB
pg_toast.pg_toast_43934449_index | 1004 MB
pg_toast.pg_toast_43934438_index | 942 MB
pg_toast.pg_toast_16715_index | 709 MB
pg_toast.pg_toast_16813_index | 548 MB
pg_toast.pg_toast_50877_index | 530 MB
pg_toast.pg_toast_3518414 | 463 MB
pg_toast.pg_toast_16994 | 339 MB
pg_toast.pg_toast_46608 | 310 MB
pg_toast.pg_toast_16994_index | 92 MB
pg_toast.pg_toast_22345124 | 68 MB
pg_toast.pg_toast_46608_index | 51 MB
pg_toast.pg_toast_437018 | 43 MB
pg_toast.pg_toast_5706469_index | 15 MB
pg_toast.pg_toast_3518414_index | 13 MB
(20 rows)
Which is significant when the total size of the DB is currently about 420GB. This is totally expected as some of my tables are storing JSON as either text
type (for some of my older tables) or jsonb
for some of the newer ones.
A lot of these columns can be cleaned up at the application-level by just deleting some older data. The problem is that it's hard to know what's actually contributing to the pg_toast tables?
How can I reverse-trace a pg_toast to the actual row/column reference of another table?
Решение
You can use this query to find out all tables with TOAST tables:
SELECT oid::regclass,
reltoastrelid::regclass,
pg_relation_size(reltoastrelid) AS toast_size
FROM pg_class
WHERE relkind = 'r'
AND reltoastrelid <> 0
ORDER BY 3 DESC;
To find out which of the columns in the table consumes most space, you could try a query like
SELECT sum(length(col1)) AS col1_size,
sum(length(col2)) AS col2_site
FROM some_table;
Here col1
and col2
would be text
, varchar
, char
or bytea
columns, which are usually the largest ones. With other data types like jsonb
you could cast to text
to get an estimate.
Другие советы
Internally, postgres identifies pretty much everything by oids - the numeric part of your TOAST table names should be the identifier of the parent table:
From PostgreSQL.org
... the numeric part of the toast table's name is the OID of its parent, so really you just need to do
select '43934449'::regclass ;
Confirming the reltoastrelid link is a good idea though.