将列添加到Postgresql中的巨大表中,无需停机

时间:2016-04-18 12:50:11

标签: sql database postgresql

我有一个非常小的表(大约1密耳行),我将删除约束并添加新列。下面的查询挂起大约5分钟,不得不回滚。

BEGIN WORK;
LOCK TABLE usertable IN SHARE MODE;
ALTER TABLE usertable ALTER COLUMN email DROP NOT NULL;
COMMIT WORK;

另一种方法建议在互联网上的类似问题 -

CREATE TABLE new_tbl
(
  field1 int,
  field2 int,
  ...
);

INSERT INTO new_tbl(field1, field2, ...)
(
  SELECT FROM ... -- use your new logic here to insert the updated data
)

CREATE INDEX -- add your constraints and indexes to new_tbl

DROP TABLE tbl;

ALTER TABLE tbl_new RENAME tbl;
  1. 创建新表
  2. 将旧表中的记录插入新表(少于一秒)
  3. 删除旧表 - 此查询挂起约5分钟〜。不得不回滚。对我不起作用。
  4. 将新创建的表重命名为旧表
  5. 删除旧表只是挂起。但是,当我尝试删除包含100万行的新创建表时 - 它会立即生效。为什么丢弃旧桌需要花费很多时间?

    SELECT blocked_locks.pid     AS blocked_pid,
             blocked_activity.usename  AS blocked_user,
             blocking_locks.pid     AS blocking_pid,
             blocking_activity.usename AS blocking_user,
             blocked_activity.query    AS blocked_statement,
             blocking_activity.query   AS blocking_statement
       FROM  pg_catalog.pg_locks         blocked_locks
        JOIN pg_catalog.pg_stat_activity blocked_activity  ON blocked_activity.pid = blocked_locks.pid
        JOIN pg_catalog.pg_locks         blocking_locks
            ON blocking_locks.locktype = blocked_locks.locktype
            AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
            AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
            AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
            AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
            AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
            AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
            AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
            AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
            AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
            AND blocking_locks.pid != blocked_locks.pid
        JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
       WHERE NOT blocked_locks.granted;
    

    我可以看到许多正在等待我操作的并发写入/读取。自从我把锁放在桌子上,我真的不认为我之所以不能放弃旧桌子。

    只是在旧桌子上运行真空,它没有帮助。

    为什么我不能删除旧表为什么与删除最近创建的表相比需要花费这么多时间?

2 个答案:

答案 0 :(得分:1)

我没有很多PostgreSQL的经验,但我的猜测是,当NULL能列为NULL时(而不是空),它会保留一点意思当该列标记为NOT NULL时,它不再需要该位。因此,当您更改列上的该属性时,系统需要遍历整个表并重新排列数据,移动大量位以使行正确构造。

这与DROP TABLE有很大的不同,%y只需要将磁盘空间标记为不再使用,并且可能更新一些元数据值。

简而言之,他们的行动非常不同,所以他们当然会花费不同的时间。

答案 1 :(得分:1)

我无法删除/重命名其他表的FK表原始表原因。一旦我下载它,重命名表的方法很好