Select table size and row counts for specific schema - postgresql

I need to have a query that would give me the information for each table in specific schema. The information would be the size of the table (best in Mb) and also the row counts. I prepared some query as below but not sure if the result is in megabytes. Moreover i do not know how to get the row counts from information_schema.tables. Can somebody help?
This is my current query:
select table_name, pg_relation_size(quote_ident(table_name))
from information_schema.tables
where table_schema = 'myschema'
order by 2;
EDIT:
By this i can get row counts nevertheless do not know how to filter based on specific schema and how to add table size in Mb to it.
select nspname as schema, relname as tablename,
reltuples as rowcounts
from pg_class c JOIN pg_catalog.pg_namespace n
ON n.oid = c.relnamespace where relkind='r'
and relname like 't%'
order by nspname, reltuples desc;

You can get the size of the table in megabytes using the pg_relation_size function. By default the function will return the result in bytes, but you can convert the result to megabytes. Also, to filter by a specific scheme, use the table_schema entry from information_schema.tables.
SELECT
table_name,
(pg_relation_size(quote_ident(table_name)) / 1024 /1024) size,
reltuples as rowcounts FROM information_schema.tables ist
left join pg_class pc on pc.relname = ist.table_name
WHERE table_schema = 'public'
Demo in sql<>daddy.io

Related

Find number of rows on each table in a schema in postgres

I'm running this in Postgres 9.4 to get the number of rows on each table in a particular schema:
select table_schema, table_name,
(xpath('/row/count/text()', query_to_xml('select count(*) from '||format('%I.%I', table_schema, table_name), true, true, '')))[1]::text::int as row_count
from information_schema.tables
where table_schema = 'pricing'
It works in Postgres 9.4 but in Postgres 8.4 I get an error saying format function doesn't exist, is there a similar function in postgres 8.4?
In postgres 8.4 I get this:
function format(unknown, information_schema.sql_identifier,
information_schema.sql_identifier) does not exist
Thanks!
All the table row counts in all schema
SELECT relname, n_tup_ins - n_tup_del as rowcount FROM pg_stat_all_tables;
All the table row counts in the given schema
SELECT
nspname AS schemaname,relname,reltuples
FROM pg_class C
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE
nspname IN ('schema_name') AND
relkind='r'
ORDER BY reltuples DESC;

How to list MAX(id) of all tables given the db schema name?

I am looking for a pgsql query to pull the last PK for all tables given the db schema.
Need this for my db migration work.
You can do this with a variation of a dynamic row count query:
with pk_list as (
select tbl_ns.nspname as table_schema,
tbl.relname as table_name,
cons.conname as pk_name,
col.attname as pk_column
from pg_class tbl
join pg_constraint cons on tbl.oid = cons.conrelid and cons.contype = 'p'
join pg_namespace tbl_ns on tbl_ns.oid = tbl.relnamespace
join pg_attribute col on col.attrelid = tbl.oid and col.attnum = cons.conkey[1]
join pg_type typ on typ.oid = col.atttypid
where tbl.relkind = 'r'
and cardinality(cons.conkey) = 1 -- only single column primary keys
and tbl_ns.nspname not in ('pg_catalog', 'information_schema')
and typ.typname in ('int2','int4','int8','varchar','numeric','float4','float8','date','timestamp','timestamptz')
and has_table_privilege(format('%I.%I', tbl_ns.nspname, tbl.relname), 'select')
), maxvals as (
select table_schema, table_name, pk_column,
(xpath('/row/max/text()',
query_to_xml(format('select max(%I) from %I.%I', pk_column, table_schema, table_name), true, true, ''))
)[1]::text as max_val
from pk_list
)
select table_schema,
table_name,
pk_column,
max_val
from maxvals;
The first CTE (pk_list ) retrieves the name of the primary key column for each "user" table (that is: tables that are not system tables)
The second CTE (maxvals) then creates a select statement that retrieves the max value for each PK column from the first CTE and runs that query using query_to_xml(). The xpath() function is then used to parse the XML and return the max value as a text value (so it's possible to mix numbers and varchars)
The final select then simply displays the result from that.
The above has the following restrictions:
Only single-column primary keys are considered
It only deals with data types that support using max() on them (e.g. UUID columns are not included)

Count file size in PostgreSQL

I have this simple table which I would like to use to store files.
CREATE TABLE table(
ID INTEGER NOT NULL,
FILE_NAME TEXT,
FILE OID
)
;
Is there any way with SQL query to count the total size of the files into the table? Is this possible without function?
rzo is close but not quite right.
select file_name, pg_column_size(lo_get(oid)) from files;
Gives you the size in bytes.
If you want pretty printing:
select file_name, pg_size_pretty(pg_column_size(lo_get(oid))::numeric) from files;
If you are interested in the total disk size (disk usage), you could do something like:
SELECT nspname || '.' || relname AS "relation",
pg_size_pretty(pg_relation_size(C.oid)) AS "size"
FROM pg_class C
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE nspname NOT IN ('pg_catalog', 'information_schema')
ORDER BY pg_relation_size(C.oid) DESC
LIMIT 20;
Other queries to measure the size of relations can be found in the PostgreSQL Wiki

Record table and schema sizes in PostgreSQL

Is thre a simple way to query for the size of a postgres database?
I am trying to do something like this:
select 'session_metrics',pg_size_pretty(pg_total_relation_size('schema1.session_metrics'))
union
select 'transaction_metrics',pg_size_pretty(pg_total_relation_size('schema1.transaction_metrics'))
union
select 'cookie_user_metrics',pg_size_pretty(pg_total_relation_size('schema1.cookie_user_metrics'))
union
select 'cookie_transaction_metrics',pg_size_pretty(pg_total_relation_size('schema1.cookie_transaction_metrics'));
And store those values in a table so that I can later easily track the growth rates of my tables.
The problem is I now have over 50 different tables and I don't want to add a line of query every time I create a new table.
I would appreciate if someone could orient me to something like:
select table_name, schema_name, size;
The 'table names' table you're looking for is pg_catalog.pg_namespace.
The following query is adapted from the psql \d command:
SELECT n.nspname as "Schema",
c.relname as "Name",
pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as "Size",
now() as "Timestamp"
FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname <> 'pg_catalog'
AND n.nspname <> 'information_schema'
AND n.nspname !~ '^pg_toast'
I have taken the liberty of adding a timestamp since you are planning to compare sizes over time.

pg_relation_size tells me column doesn't exist

http://www.postgresql.org/docs/8.4/static/functions-admin.html says:
pg_relation_size
accepts the OID or name of a table, index or toast table, and returns the size in bytes
However when I use it with a valid table name, I get the error:
column [table] does not exist...
I know my table exists, because doing
SELECT count(*) FROM [table]
returns a valid number. Any ideas?
I got the same error though the cause was different. pg_relation_size is case insensitive, so if you have anything other than lower case it will not work out of the box:
postgres=> SELECT pg_size_pretty(pg_total_relation_size('MyTable'));
ERROR: relation "mytable" does not exist
LINE 1: SELECT pg_size_pretty(pg_total_relation_size('mytable...
^
postgres=> SELECT pg_size_pretty(pg_total_relation_size('"MyTable"'));
pg_size_pretty
----------------
225 MB
(1 row)
So in order for this to work in a SELECT statement you need to enclose the table name in quotes:
postgres=> SELECT relname, nspname, pg_size_pretty(pg_relation_size('"' || relname || '"'))
FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind IN ('r','') AND n.nspname NOT IN ('pg_catalog', 'pg_toast') AND pg_table_is_visible(c.oid)
ORDER BY c.relpages DESC;
Try explicitely adding the schema (e.g. 'public') where the table is located in the pg_relation_size call.
Like this (untested):
select pg_relation_size(public.mytablename) from pg_tables