I have a table with only integer and smallint columns, adding up to 20 bytes. pg_column_size
reports 44. This is expected due to the 24-byte per-row overhead, as explained in Difference between pg_column_size(table.*) and pg_column_size(table.col1) + pg_column_size (table.col2)
However, if I divide pg_table_size
by the number of rows I get ~53 bytes per row, even with hundreds of millions of rows. Where are these extra 9 bytes coming from?
I can reproduce this even with one integer column:
drop table if exists anint;
create table anint
as
select generate_series
from generate_series(1, 10000000);
select pg_column_size(e.*) -- 28
from anint e
limit 1;
select n_live_tup as row_count_estimate, -- 10000000
pg_size_pretty(pg_table_size(relid)) as table_size, -- 346 MB
case when n_live_tup = 0 then null else pg_table_size(relid) / cast(n_live_tup as float) end as table_bytes_per_row -- 36.2561536
from pg_catalog.pg_statio_user_tables io
join pg_catalog.pg_stat_user_tables s using (relid)
where io.schemaname = 'public' and io.relname = 'anint'
This returns ~36 bytes/row, not 28. (Tested on PostgreSQL 14.1.)