Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with dba.stackexchange
scroll top