添加没有表锁的新列?

时间:2012-05-02 10:39:42

标签: sql postgresql heroku locking thinking-sphinx

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

早些时候,我测试了为Thinking Sphinx搜索添加增量列,但它将整个数据库锁定为一小时。之后,当添加文件并尝试重建索引时,这是保存数据库锁大约4小时的查询:

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

为了使服务器运行起来,我从db dump创建了一个新的数据库,并将其作为数据库提升,以便服务器可以实时转动。

现在我正在寻找的是在我的表中添加delta列而不是表锁是可能的吗?一旦添加了列delta,为什么在运行index rebuild命令时执行上述查询,为什么它会长时间阻塞服务器?

PS:我在Heroku上使用Postgres和ika db模型。

2 个答案:

答案 0 :(得分:3)

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

如果您的数据模型和可用磁盘空间允许, CREATE 在后台新表,然后在一个事务中:DROP旧表,< strong> RENAME 新的 详情和注意事项related later answer on dba.SE

此外,如果表的主要部分受到影响,请在执行批量UPDATE之前删除所有索引,因为所有索引也必须更新。删除它们并在完成批量更新后重新创建它们会更快。

最后,在后台创建新表时:一次应用所有更改,或者创建受影响行的多个更新版本。

免责声明:添加不含DEFAULT(= DEFAULT NULL)的新列通常不会创建新行,并且本身非常便宜。向其中添加值会创建新行 Details in the maunal

如果由于约束而无法移除原始表格,另一种快速方法是构建临时表格, TRUNCATE 原始表格和质量 INSERT 新行 - 排序,如果这有助于提高性能。一次性交易。像这样:

BEGIN

SET temp_buffers = 1000MB;  -- or whatever you can spare temporarily

CREATE TEMP TABLE tmp AS
SELECT * FROM tbl LIMIT 0; -- copy layout of table

ALTER TABLE tmp ADD column delta boolean; -- NOT DEFAULT

INSERT INTO tmp (col1, col2, ... , delta)
SELECT col1, col2, ... , FALSE
FROM   tbl;                -- copy existing rows plus new value
-- ORDER BY ???

-- 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
SELECT * FROM tmp;         -- insert back surviving rows.

-- recreate all indexes here

COMMIT;

答案 1 :(得分:0)

您可以使用一列添加另一个表,不会有任何此类长锁。当然应该有另一列,第一列的外键。

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