在我的项目中,有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模型。
答案 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上使用太重的锁。