I have 2 tables with the below schemas with equal number of rows. When I run the SELECT relname, relpages FROM pg_class ORDER BY relpages DESC command, they show up as 23GB each even though the data types (total number of bytes) for thew two schemas result in different sizes . What is the best way to figure out how much space I would save by combining tables? Also, is there any way to determine, how much space each row is actually taking up?

                                 Table "public.table1"
Column        |           Type           |                      Modifiers                      

 field1       | smallint                 | 
 field2       | smallint                 | 
 field3       | integer                  | 
 field4       | smallint                 | 
 timestamp    | timestamp with time zone | 
 user_id      | integer                  | 
 status       | boolean                  | 
 id           | integer                  | not null default 

                                  Table "public.table2"
 Column          |           Type           |                     Modifiers                      
 user_id         | integer                  | 
 begin_timestamp | timestamp with time zone | 
 end_timestamp   | timestamp with time zone | 
 field           | smallint                 | not null
 id              | integer                  | not null default 
  • do they have the same primary key? Aug 5, 2011 at 17:30
  • Yes, the id fields in both tables are primary keys Aug 8, 2011 at 16:06

2 Answers 2


A reasonable answer to this must IMHO ask (or at least imply) the question: Why were the tables split to begin with? (More importantly: Does it apply still?)

The general case: I do not know the specifics of how the postgres db engine works, but the lower bound of saved disk space may be no larger than the size of the columns removed + indexes of duplicate variables + a bit of housekeeping data

The upper bound is also quite small, so it's probably not going to be worth the trouble; it may even be that they were partitioned for performance reasons - because some columns would be accessed (read, or even updated) more often, and as such it could be made small (fewer columns) to make it faster. (At some penalty for accessing columns from both at the same time.)

The specific case: It looks like there's a lot of redundant fields between them. user_id, for example, would not need to be there twice. begin/end/X timestamps could perhaps be reduced to two or one. So there could be some slight saving from that, depending on the application's requirements. Again, try to figure out why they did it to begin with.

Overall, though, I agree with Bryan Agee; disk space should probably not be your concern on anything big enough to run postgres to begin with. Particularly if you get paid for the time you spend on "fixing" this, that cost is likely to exceed the cost of the bigger disk by itself.

Per-row space: I'm not well versed in postgres particulars, so someone in the know should be able to correct anything wrong. Such as there being way to ask postgres how much space that specific row is actually taking up; I don't know any. What I'm writing is basically the theory behind database storage as (I believe) commonly done today.

Each field has a bit (in a byte of its own, or in a bitset common for the whole row) which says if the value is a null or not. If it's a null value, there's nothing more stored. Then there's a length byte - unless this is implicit from fixed-width data types. Then there's the data itself.

Thus, a row of one int (even 64-bit) and three null values may take as little as 3 bytes. (For values <127, storing size=1 and the byte.) Plus indexes, and various other housekeeping metadata. Again, I don't know just how far postgres goes in this regard. And these factors all taken together will tend to make "how much does this row occupy" a question with a useless answer.

AFAIK postgres also operates with "pages" - blocks of space that a row may not be stored across the boundaries of. So, larger records may more often end up "just not fitting" in a page and so need to be placed in another/new page.


Because the resulting combined table would have unused rows for records from each respective table, the likelihood is that you would not gain space, but lose it.

More importantly than that, I would highly discourage making an architecture decision of that nature for reasons of disk-space. Disks are cheap--a well designed and functional application is not. If there is an issue of run-time performance (ie all 46 gb is being loaded into memory/swap space) then you may have an optimization and tuning issue on your hands.

  • "2 tables with the below schemas with equal number of rows" implies that there is a 1 to 1 relationship Aug 6, 2011 at 10:14
  • @Jack are you suggesting that a 1 to 1 relationship is bad? I think it's quite subjective, I have found them quite useful in a couple of implementations (not using PostgreSQL, admittedly). Aug 6, 2011 at 17:52
  • @Aaron - no, I was referring to "the resulting combined table would have unused rows for records from each respective table" Aug 6, 2011 at 17:58
  • Ah, sorry for the misinterpretation. Aug 6, 2011 at 18:07

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.