PostgreSQL provides a number of Database Object Size Functions, you can use. I packed the most interesting ones in this query and added some Statistics Access Functions.
This is going to demonstrate that the various methods to measure the "size of a row" can lead to very different results. It all depends what you want to measure exactly.
Replace schema.tbl with your table name to get a compact view of collected statistics about the size of your rows.
WITH x AS (
SELECT count(*) AS ct
,sum(length(t::text)) AS txt_len -- length in characters
,'schema.tbl'::regclass AS tbl
FROM schema.tbl t
)
, y AS (
SELECT ARRAY [
pg_relation_size(tbl)
,pg_relation_size(tbl, 'vm')
,pg_relation_size(tbl, 'fsm')
,pg_table_size(tbl)
,pg_indexes_size(tbl)
,pg_total_relation_size(tbl)
,txt_len
] AS val
,ARRAY [
'core_relation_size'
,'visibility_map'
,'free_space_map'
,'table_size_incl_toast'
,'indexes_size'
,'total_size_incl_toast_and_indexes'
,'live_rows_in_text_representation'
] AS name
FROM x
)
SELECT unnest(name) AS what
,unnest(val) AS bytes
,pg_size_pretty(unnest(val)) AS bytes_pretty
,unnest(val) / ct AS per_row_bytes
FROM x,y
UNION ALL
SELECT '----------'::text, NULL::int8, '----'::text, NULL::int8
UNION ALL
SELECT 'row_count'::text, ct
,NULL::text, NULL::bigint FROM x
UNION ALL
SELECT 'live_tuples'::text, pg_stat_get_live_tuples(tbl)
,NULL::text, NULL::bigint FROM x
UNION ALL
SELECT 'dead_tuples'::text, pg_stat_get_dead_tuples(tbl)
,NULL::text, NULL::bigint FROM x;
I only pack the values in arrays and unnest() again, so I don't have to spell out calculations for every single row repeatedly.
General row count statistics are appended at the end with unconventional SQL-foo to get everything in one query. You could wrap it into a plpgsql function for repeated use, hand in the table name as parameter and use EXECUTE.
Result:
what | bytes | bytes_pretty | per_row_bytes
-----------------------------------+----------+--------------+---------------
core_relation_size | 44138496 | 42 MB | 91
visibility_map | 0 | 0 bytes | 0
free_space_map | 32768 | 32 kB | 0
table_size_incl_toast | 44179456 | 42 MB | 91
indexes_size | 33128448 | 32 MB | 68
total_size_incl_toast_and_indexes | 77307904 | 74 MB | 159
live_rows_in_text_representation | 29987360 | 29 MB | 62
---------- | | ---- |
row_count | 483424 | |
live_tuples | 483424 | |
dead_tuples | 2677 | |
The additional module pgstattuple provides more useful functions.
idbeing indexed while the whole row being not. If you do anEXPLAIN ANALYZEand paste its result here (or, if it is too long, explain.depesz.com ), we could see something. – dezso Sep 7 '12 at 9:46length(*)rather than justlength(field)? I know that's chars not bytes but I only need an approx value. – Joe Sep 7 '12 at 9:51select length(row(n.*)::text) from pg_namespace n;? – Jack Douglas♦ Sep 7 '12 at 11:25select length(n::text) from pg_namespace n;– Erwin Brandstetter Sep 7 '12 at 14:05