Question

I have a table with columns and constraints:

height smallint,
length smallint,
diameter smallint,
volume integer,
idsensorfragments integer,
CONSTRAINT sensorstats_idsensorfragments_fkey FOREIGN KEY (idsensorfragments)
  REFERENCES sensorfragments (idsensorfragments) MATCH SIMPLE
  ON UPDATE CASCADE ON DELETE CASCADE

(no primary key). There is currently 28 978 112 records in it, but the size of the table is way too much in my opinion.

Result of the query:

select pg_size_pretty(pg_total_relation_size('sensorstats')), pg_size_pretty(pg_relation_size('sensorstats'))

is:

"1849 MB";"1226 MB"

There is just one index on idsensorfragments column. Using simple math you can see that one record takes ~66,7 B (?!?!). Can anyone explain me where this number comes from?

5 columns = 2 + 2 + 2 + 4 + 4 = 14 Bytes. I have one index, no primary key. Where additional 50B per record comes from?

P.S. Table was vacuumed, analyzed and reindexed.

Was it helpful?

Solution

You should take a look on how Database Physical Storage is organized, especially on the Page Layout.

PostgreSQL keeps a bunch of extra fields for each tuple (row) and also for each Page. Tuples are kept in the Pages, as Page is the item that database operates on, typically 8192 bytes in size. So the extra space usage comes from:

  • PageHeader, 24 bytes;
  • Tupleheader, 27 bytes;
  • “invisible” Tuple versions;
  • reserved free space, according to the Storage Parameters of the table;
  • NULL indicator array;
  • (might have missed something more).

The layout of physical storage changes between major releases, that's the reason you have to perform a full dump/restore. In the recent versions pg_upgrade is of great help in this process.

OTHER TIPS

Did you do a VACUUM FULL or CLUSTER? If not, the unused space is still dedicated to this table and index. These statements rewrite the table, a VACUUM without FULL doesn't do the rewrite.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top