postgresqlauto-incrementidentitycompact-database

Compact or renumber IDs for all tables, and reset sequences to max(id)?


After running for a long time, I get more and more holes in the id field. Some tables' id are int32, and the id sequence is reaching its maximum value. Some of the Java sources are read-only, so I cannot simply change the id column type from int32 to long, which would break the API.

I'd like to renumber them all. This may be not good practice, but good or bad is not concerned in this question. I want to renumber, especially, those very long IDs like "61789238", "548273826529524324". I don't know why they are so long, but shorter IDs are also easier to handle manually.

But it's not easy to compact IDs by hand because of references and constraints.

Does PostgreSQL itself support of ID renumbering? Or is there any plugin or maintaining utility for this job?

Maybe I can write some stored procedures? That would be very nice so I can schedule it once a year.


Solution

  • Assuming your ids are generated from a bignum sequence, just RESTART the sequence and update the table with idcolumn = DEFAULT.

    CAVEAT: If this id column is used as a foreign key by other tables, make sure you have the on update cascade modifier turned on.

    For example:

    Create the table, put some data in, and remove a middle value:

    db=# create sequence xseq;
    CREATE SEQUENCE
    db=# create table foo ( id bigint default nextval('xseq') not null, data text );
    CREATE TABLE
    db=# insert into foo (data) values ('hello'), ('world'), ('how'), ('are'), ('you');
    INSERT 0 5
    db=# delete from foo where data = 'how';
    DELETE 1
    db=# select * from foo;
     id | data  
    ----+-------
      1 | hello
      2 | world
      4 | are
      5 | you
    (4 rows)
    

    Reset your sequence:

    db=# ALTER SEQUENCE xseq RESTART;
    ALTER SEQUENCE
    

    Update your data:

    db=# update foo set id = DEFAULT;
    UPDATE 4
    db=# select * from foo;
     id | data  
    ----+-------
      1 | hello
      2 | world
      3 | are
      4 | you
    (4 rows)