5

I need to reclaim disk space in a table in a Postgresql 9.3.2 database to be used for other tables. The standard suggestions to accomplish this are: "VACUUM FULL" or "CLUSTER" or copy the contents into a flat file and copy them back in. When moving an existing table to a new tablespace with an "ALTER TABLE" command, the table's contents are copied. Can anyone tell me if they are compacted during the "ALTER TABLE" process?

4
  • Very good question; depends on whether the relfilenodes are copied or it's done as a relation rewrite. I'd have to check the source code. If you don't get a definitive answer soon, at-reply me and I'll go check. Commented Dec 29, 2014 at 17:18
  • I could very easily be wrong, but I was under the impression that postgres executed the alter tablespace on the table by simply moving the corresponding data file to the correct folder at the file-system level. If what I said above is true, then I doubt it would reclaim any space. Commented Dec 29, 2014 at 23:24
  • @CraigRinger as a PG contributor, would you know how hard would that be to implement in future version? Many use cases for changing tablespaces are "disk full" problems where the ALTER TABLE would immediately be followed by a VACUUM FULL. Commented Aug 8, 2024 at 10:54
  • @Matthieu Honestly no idea, I haven't dug much into that part of the storage manager and haven't been as active in Pg recently. You'd want to ask on the mailing lists. Commented Aug 11, 2024 at 23:08

2 Answers 2

5

The comments so far are roughly correct, but to give an authoritative answer from looking at src/backend/tablecmds.c:

If you're only performing ALTER TABLE ... SET TABLESPACE ... ;, then ATExecSetTableSpace() will be invoked to handle the SET TABLESPACE, and it uses copy_relation_data() to perform a WAL-logged block-by-block copy of the table. However, if you were to specify additional actions to the ALTER TABLE command which require table rewriting, then the new copy of the table should be built (and compacted) in the new tablespace via ATRewriteTable().

3
  • 1
    Are there any trivial "additional actions" that will cause ATRewriteTable? By "trivial" I mean "actions that won't break existing sql code". Perhaps changing a column name to the same value as it is presently? Commented Jan 2, 2015 at 16:51
  • 1
    @sevzas it's going to depend on your exact PostgreSQL version and column type, but using something like SET DATA TYPE some_int_col USING some_int_col::bigint::int should probably work (just casting the column to its own type probably won't be enough to force a rewrite, depending on your PG version). Commented Jan 2, 2015 at 17:16
  • Do you think that would still hold 9 years later? Commented Aug 8, 2024 at 11:16
4

The answer appears to be "moving the table to a different tablespace does not compact it like VACUUM FULL or CLUSTER".

I tested this by:

  • creating a dummy table
  • filling it with one million dummy rows to the tune of 38MB
  • deleting all of the rows with "DELETE from DUMMY"
  • moving table to a different tablespace with "ALTER TABLE DUMMY SET TABLESPACE overflow;"
  • looking to see how big the table is on the new table space.

The query I used to determine the size of the table is this:

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;
1
  • Did you have a chance to test @JoshKupershmidt's suggestion? (adding dummy statement to make the compaction) Commented Aug 8, 2024 at 11:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.