我在数据库中有一个需要转换为数组类型的字符串列。在我还需要设置索引的过程中,不应该锁定数据库。
ALTER TABLE sites ALTER COLUMN rtb_id TYPE varchar[] USING string_to_array(rtb_id, '');
CREATE INDEX CONCURRENTLY rtb_id_search ON sites(rtb_id) USING array_to_string;
DROP INDEX CONCURRENTLY ix_sites_bundle_trgm_gin ON sites;
DROP INDEX CONCURRENTLY ix_sites_name_trgm_gin ON sites;
这是这样做的吗?
编辑:
ALTER TABLE sites ADD COLUMN rtb_ids varchar[]
...
BEFORE INSERT OR UPDATE ... FOR EACH ROW trigger that sets NEW.rtb_id_new := string_to_array(NEW.rtb_id,' ') for each row.
In batches, UPDATE sites SET rtb_id_new = string_to_array(rtb_id,' ')
...
VACUUM sites;
CREATE INDEX CONCURRENTLY rtb_ids_search ON sites(rtb_ids) USING array_to_string(rtb_ids, '');
ALTER TABLE sites DROP COLUMN rtb_id;
由于
答案 0 :(得分:1)
It is not possible to do it without locks. You can do it with relatively few short-lived strong locks, though.
The ALTER TABLE
will take an exclusive lock for a long while at the moment because it does a full table rewrite.
Instead you'll need to:
ALTER TABLE sites ADD COLUMN rtb_id_new varchar[]
BEFORE INSERT OR UPDATE ... FOR EACH ROW
trigger that sets NEW.rtb_id_new := string_to_array(NEW.rtb_id,' ')
for each row.UPDATE sites SET rtb_id_new = string_to_array(rtb_id,' ')
VACUUM sites;
then ALTER TABLE sites ALTER COLUMN rtb_id_new NOT NULL
. This will take an exclusive lock for long enough to do a sequential scan, so it's not going to be super-fast. On PostgreSQL 9.5 the lock taken is weaker and won't stop SELECT
s.CONCURRENTLY
ALTER TABLE sites DROP COLUMN rtb_id; ALTER TABLE sites RENAME COLUMN rtb_id_new TO rtb_column;
UNIQUE
constraints, add them USING
the indexes already built to minimise lock durations.This isn't totally lock-free. In particular the NOT NULL
constraint will hurt because PostgreSQL doesn't (yet) know how to add a NOT NULL
constraint as NOT VALID
then validate it.