Domanda

I want to alter column data type from float4 to float8 on a table with huge rows count. If I do it in usual path it takes much time and my table blocked for this time. IS any hack to do it without rewrite the table content?

È stato utile?

Soluzione

ALTER TABLE ... ALTER COLUMN ... TYPE ... USING ... (or related things like ALTER TABLE ... ADD COLUMN ... DEFAULT ... NOT NULL) requires a full table rewrite with an exclusive lock.

You can, with a bit of effort, work around this in steps:

  • ALTER TABLE thetable ADD COLUMN thecol_tmp newtype without NOT NULL.

  • Create a trigger on the table that, for every write to thecol, updates thecol_tmp as well, so new rows that're created, and rows that're updated, get a value for newcol_tmp as well as newcol.

  • In batches by ID range, UPDATE thetable SET thecol_tmp = CAST(thecol AS newtype) WHERE id BETWEEN .. AND ..

  • once all values are populated in thecol_tmp, ALTER TABLE thetable ALTER COLUMN thecol_tmp SET NOT NULL;.

  • Now swap the columns and drop the trigger in a single tx:

    • BEGIN;
    • ALTER TABLE thetable DROP COLUMN thecol;
    • ALTER TABLE thetable RENAME COLUMN thecol_tmp TO thecol;
    • DROP TRIGGER whatever_trigger_name ON thetable;
    • COMMIT;

Ideally we'd have an ALTER TABLE ... ALTER COLUMN ... CONCURRENTLY that did this within PostgreSQL, but nobody's implemented that. Yet.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top