How can I list all the tables of a PostgreSQL database and order them by size?
-
4If you are using the command-line psql client then a simple `\d+` will show you this information, though unsorted. – cdhowie Feb 12 '14 at 20:08
-
1Thanks. But I *need it* sorted, I have too many tables. – nothing-special-here Feb 12 '14 at 20:09
-
2People looking for the same thing but for databases instead of tables : [here is the solution](https://stackoverflow.com/a/18907188/812102). – Skippy le Grand Gourou Jun 12 '17 at 10:46
-
3Re psql: start it with --echo-hidden and it will tell you the queries done for \d+ and other backslash commands. Easy to add sorting. – Jürgen Strobel Oct 16 '18 at 20:41
14 Answers
select
table_name,
pg_size_pretty(pg_relation_size(quote_ident(table_name))),
pg_relation_size(quote_ident(table_name))
from information_schema.tables
where table_schema = 'public'
order by 3 desc;
This shows you the size of all tables in the schema public
if you have multiple schemas, you might want to use:
select table_schema, table_name, pg_relation_size('"'||table_schema||'"."'||table_name||'"')
from information_schema.tables
order by 3
SQLFiddle example: http://sqlfiddle.com/#!15/13157/3
List of all object size functions in the manual.

- 148,955
- 89
- 346
- 502
-
It's table_schema, not schema_name. The first query was fine but you had already started typing something in your psql session, which caused a syntax error. – yieldsfalsehood Feb 12 '14 at 20:13
-
5OK this code works: `select table_schema, table_name, pg_relation_size(table_schema||'.'||table_name) from information_schema.tables order by 3; ` thanks for help! – nothing-special-here Feb 12 '14 at 20:19
-
any idea what this dont work in my case? http://stackoverflow.com/questions/40977776/why-cant-see-my-schema-size – Juan Carlos Oropeza Dec 05 '16 at 20:14
-
@Sucrenoir: "does not work" is not a valid Postgres error message. The query in my answer does work for me: http://rextester.com/KGKPR49004 – Feb 20 '17 at 09:05
-
I get zero rows when I run the first query. `select * from information_schema.tables where table_schema = 'public';` yields zero rows even though `\dn` shows schema public. Maybe a change in 9.5 caused this? – sheepdog May 31 '17 at 10:48
-
I had to use pg_table_size instead of pg_relation_size to get the actual size as some tables were showing smaller sizes for pg_relation_size. These tables had jsonb columns. Not sure why it was happening though. – Padmika May 16 '20 at 14:10
-
11You should use `pg_total_relation_size` to get the total size of the table **including its indexes** - see https://stackoverflow.com/a/41991566/1668200 – Thomas Landauer Aug 17 '21 at 13:56
This will show you the schema name, table name, size pretty and size (needed for sort).
SELECT
schema_name,
relname,
pg_size_pretty(table_size) AS size,
table_size
FROM (
SELECT
pg_catalog.pg_namespace.nspname AS schema_name,
relname,
pg_relation_size(pg_catalog.pg_class.oid) AS table_size
FROM pg_catalog.pg_class
JOIN pg_catalog.pg_namespace ON relnamespace = pg_catalog.pg_namespace.oid
) t
WHERE schema_name NOT LIKE 'pg_%'
ORDER BY table_size DESC;
I build this based on the solutions from here list of schema with sizes (relative and absolute) in a PostgreSQL database
-
3
-
1Can be useful to add relkind to this to explicitly identifying table or index – Rob Bygrave Apr 06 '21 at 02:40
-
-
For me, pg_relation_size (line 11) only showed 8 kB on a table with a huge PickledObjectField; pg_total_relation_size showed more sensible 57 MB. You might want to check out https://stackoverflow.com/q/41991380/118520 for details. – egor83 Jul 25 '22 at 10:45
-
1Change `pg_relation_size` to `pg_total_relation_size` to include indices! – Sina Rezaei Dec 28 '22 at 07:20
This will be more clear.
pg_size_pretty(<numeric_value>)
- converts no.of bytes to human-readable format.
pg_database_size(<db_name>)
- gets database size in bytes.
pg_total_relation_size(<relation_name>)
- gets total size of table and its index in bytes.
pg_relation_size(<relation_name>)
- gets relation (table/index) size in bytes.
pg_indexes_size(<relation_name>)
- gets index size of the relation in bytes.
current_database()
- gets the currently used database on which this query is being performed.
Query:
select current_database() as database,
pg_size_pretty(total_database_size) as total_database_size,
schema_name,
table_name,
pg_size_pretty(total_table_size) as total_table_size,
pg_size_pretty(table_size) as table_size,
pg_size_pretty(index_size) as index_size
from ( select table_name,
table_schema as schema_name,
pg_database_size(current_database()) as total_database_size,
pg_total_relation_size(table_name) as total_table_size,
pg_relation_size(table_name) as table_size,
pg_indexes_size(table_name) as index_size
from information_schema.tables
where table_schema=current_schema() and table_name like 'table_%'
order by total_table_size
) as sizes;
Result:
database | total_database_size | schema_name | table_name | total_table_size | table_size | index_size
-----------+---------------------+-------------+------------+------------------+------------+------------
vigneshdb | 1586 MB | corpdata | table_aaa | 16 kB | 0 bytes | 8192 bytes
vigneshdb | 1586 MB | corpdata | table_bbb | 24 kB | 0 bytes | 16 kB
vigneshdb | 1586 MB | corpdata | table_ccc | 640 kB | 112 kB | 488 kB
vigneshdb | 1586 MB | corpdata | table_ddd | 9760 kB | 3152 kB | 6568 kB
vigneshdb | 1586 MB | corpdata | table_eee | 1120 MB | 311 MB | 808 MB
The humanized format is represent in bytes
, kB
, MB
, GB
, and TB
.
bytes
to kB
- begins from 10240 bytes
bytes
to MB
- begins from 10485248 bytes
= 10239.5 kB
~ 10 MB
bytes
to GB
- begins from 10736893952 bytes
= 10239.5 MB
~ 10 BG
bytes
to TB
- begins from 10994579406848 bytes
= 10239.5 GB
~ 10 TB
All unit conversions starts from 10 + <unit>
.
For reference - Postgres Official Documentation

- 5,859
- 2
- 34
- 27

- 7,927
- 1
- 33
- 42
-
3
-
3In more recent Postgres versions such as 12.4, this query gives an error - the fix is to [use quote_ident()](https://stackoverflow.com/a/65417941/992887) around the `table_name`. – RichVel Nov 05 '21 at 06:16
-
I like following statement:
SELECT
table_name,
pg_size_pretty( pg_total_relation_size(quote_ident(table_name))),
pg_total_relation_size(quote_ident(table_name))
FROM
information_schema.tables
WHERE
table_schema = 'public'
ORDER BY
pg_total_relation_size(quote_ident(table_name)) DESC
You can see total size in a pretty format, but it is ordered correctly too.

- 8,221
- 1
- 59
- 63
SELECT
relname as "Table",
pg_size_pretty(pg_total_relation_size(relid)) As "Size",
pg_size_pretty(pg_total_relation_size(relid) - pg_relation_size(relid)) as "External Size"
FROM pg_catalog.pg_statio_user_tables ORDER BY pg_total_relation_size(relid) DESC;
taken from here https://wiki-bsse.ethz.ch/display/ITDOC/Check+size+of+tables+and+objects+in+PostgreSQL+database

- 1,731
- 2
- 19
- 24
I needed to find which tables use the most space.
Based on other answers, I used that query:
select table_name, pg_size_pretty( pg_relation_size(quote_ident(table_name)) )
from information_schema.tables
where table_schema = 'public'
order by pg_relation_size(quote_ident(table_name)) desc
I get the following result:
table_name pg_size_pretty
--------------------------------------
trade_binance 96 GB
closs_v2_binance_stash 46 GB
closs_bitfinex_stash 5725 MB
trade_bitfinex 5112 MB
...
api_requests 0 bytes
trade_huobi 0 bytes
I should have bought a bigger SSD.

- 40,265
- 44
- 171
- 236
SELECT nspname || '.' || relname AS "relation",
pg_size_pretty(pg_total_relation_size(C.oid)) AS "total_size"
FROM pg_class C
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE nspname NOT IN ('pg_catalog', 'information_schema')
AND C.relkind <> 'i'
AND nspname !~ '^pg_toast'
ORDER BY pg_total_relation_size(C.oid) DESC
;
Credit: https://makandracards.com/makandra/52141-postgresql-how-to-show-table-sizes

- 151
- 1
- 6
If you're looking for a breakdown in total, toast and index sizes use this:
SELECT *, pg_size_pretty(total_bytes) AS total
, pg_size_pretty(index_bytes) AS INDEX
, pg_size_pretty(toast_bytes) AS toast
, pg_size_pretty(table_bytes) AS TABLE
FROM (
SELECT *, total_bytes-index_bytes-COALESCE(toast_bytes,0) AS table_bytes
FROM (
SELECT c.oid,nspname AS table_schema, relname AS TABLE_NAME
, c.reltuples AS row_estimate
, pg_total_relation_size(c.oid) AS total_bytes
, pg_indexes_size(c.oid) AS index_bytes
, pg_total_relation_size(reltoastrelid) AS toast_bytes
FROM pg_class c
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE relkind = 'r'
) a
) a ORDER BY total_bytes DESC;

- 652
- 9
- 12
select table_name,n_live_tup, pg_size_pretty(pg_relation_size(table_name))
from information_schema.tables
inner join pg_stat_user_tables on table_name=relname
where table_schema = 'public'
order by 2 desc
Another alternative

- 189
- 2
- 8
You can get total relation size and relation size, which may be different depending on your tables relationships. Now here's how to get top 100 tables on your database:
SELECT schemaname AS table_schema,
relname AS table_name,
PG_SIZE_PRETTY(PG_TOTAL_RELATION_SIZE(relid)) AS total_size,
PG_SIZE_PRETTY(PG_RELATION_SIZE(relid)) AS data_size,
PG_SIZE_PRETTY(PG_TOTAL_RELATION_SIZE(relid) - PG_RELATION_SIZE(relid))
AS external_size
FROM pg_catalog.pg_statio_user_tables
ORDER BY PG_TOTAL_RELATION_SIZE(relid) DESC,
PG_RELATION_SIZE(relid) DESC
LIMIT 100;

- 789
- 10
- 11
select table_name, pg_size_pretty(pg_total_relation_size(quote_ident(table_name)))
from information_schema.tables
where table_schema = 'public'
order by pg_total_relation_size(quote_ident(table_name));
pg_total_relation_size
would include size of indexes as well as tables.
If you want only the table size, then pg_relation_size
would be enough.

- 183
- 1
- 11
It can be easily done from psql
console.
Table Size:
\dt+
Database size
\l+
Index size:
\di+
For table size, first connect the database using \c db_name
.
Please Note: Above won't sort by size as OP asked, still it could help.

- 2,527
- 1
- 19
- 43
select uv.a tablename, pg_size_pretty(uv.b) sizepretty
from (select tb.tablename a, pg_table_size('schemaname.'||tb.tablename::text) b
from pg_tables tb
where tb.schemaname ilike 'schemaname'
order by 2 desc
) uv
-
1Your answer would be more valuable if you include an explanation as to why the suggested approach is helpful. – Cindy Meister Jan 12 '16 at 07:05
-
Its similar to horse's answer, just doing sorting by size with pretty since sort view will be easy to look. – Spike Jan 12 '16 at 07:57
-
Please add that text to your Answer, using the Edit link in the "Answer" space. Then your contribution will conform to the StackOverflow guidelines (read a bit in the Help Center) :-) – Cindy Meister Jan 13 '16 at 16:36
Most of the answers here use pg_size_pretty
which is very useful, but if you want to the output as a numerical value you can calculate this yourself like
SELECT tab_size /1024 AS size_kb
,tab_size /1024 /1024 AS size_mb
,tab_size /1024 /1024 / 1024 AS size_gb
,tab_size /1024 /1024 / 1024 / 1024 AS size_tb
FROM
(
SELECT pg_total_relation_size(relid) AS tab_size
FROM pg_catalog.pg_statio_user_tables
WHERE schemaname = 'your_schema'
AND relname = 'your_table'
) AS tabs;

- 814
- 9
- 11