要添加没有表锁的新列吗?

问题描述 投票:4回答:2

在我的拥有2300万条记录和大约6个字段的项目中,该表已被索引。

早些时候,我曾尝试为“思想狮身人面像”搜索添加delta列,但这实际上使整个数据库锁定保持了一个小时。之后,当添加文件时,我尝试重建索引,这是持有数据库锁大约4个小时的查询:

"update user_messages set delta = false where delta = true"

为组装服务器,我从db dump创建了一个新数据库,并将其升级为数据库,以便可以启用服务器。

现在,我正在寻找的是在没有表锁的情况下在我的表中添加增量列吗?一旦添加了列delta,那么为什么当我运行index rebuild命令时会执行上述查询,为什么它会阻塞服务器这么长时间?

PS .:我在Heroku上,并且使用ika db模型使用Postgres。

sql postgresql heroku locking thinking-sphinx
2个回答
4
投票

Postgres 11或更高版本

自Postgres 11起,仅易失性默认值仍需要表重写。 The manual:

[添加带有[[volatile DEFAULT的列或更改现有列的类型将需要重写整个表及其索引。

大胆强调我的。 false是不可变的。因此,只需将列添加为DEFAULT false。超快速,已完成工作:

ALTER TABLE tbl ADD column delta boolean DEFAULT false;

Postgres 10或更早版本,或用于易失性DEFAULT

添加新列

DEFAULTDEFAULT NULL通常不会强制表重写,并且非常便宜。仅向其中写入实际值会创建新行。但是,quoting the manual:

[使用DEFAULT子句添加列或更改 现有列将需要重写整个表及其索引。
PostgreSQL中的

UPDATE会写入该行的新版本。您的问题并未提供所有信息,但这可能意味着要编写数百万个新行。

在适当地执行UPDATE时,如果表的主要部分受到影响,并且您可以独占地锁定表,请在执行质量UPDATE之前删除所有索引,然后再重新创建它们。这样更快。 Related advice in the manual.

如果您的数据模型和可用磁盘空间允许,请

CREATE

在后台创建一个新表,然后在一个事务中:DROP旧表,并RENAME新的一个。相关:
  • 同时在后台创建新表时:将所有更改立即应用于同一行。重复的更新将创建新的行版本,并留下死的元组。

    If

  • 由于限制而无法删除原始表,另一种快速方法是构建临时表,TRUNCATE原始表,然后批量INSERT新行-排序(如果有帮助的话)。一站式交易。像这样的东西:BEGIN SET temp_buffers = 1000MB; -- or whatever you can spare temporarily -- write-lock table here to prevent concurrent writes - if needed LOCK TABLE tbl IN SHARE MODE; CREATE TEMP TABLE tmp AS SELECT *, false AS delta FROM tbl; -- copy existing rows plus new value -- ORDER BY ??? -- opportune moment to cluster rows -- DROP all indexes here TRUNCATE tbl; -- empty table - truncate is super fast ALTER TABLE tbl ADD column delta boolean DEFAULT FALSE; -- NOT NULL? INSERT INTO tbl TABLE tmp; -- insert back surviving rows. -- recreate all indexes here COMMIT;

    0
    投票
    您可以用一个列添加另一张表,不会有这么长的锁。当然应该有另一列,第一列的外键。

    对于索引,您可以使用“ CREATE INDEX CONCURRENTLY”,它在此表http://www.postgresql.org/docs/9.1/static/sql-createindex.html上使用的锁不太大。

    © www.soinside.com 2019 - 2024. All rights reserved.