Gul*_*ull 5 sql postgresql locking heroku thinking-sphinx
在我的项目中,该表有 2300 万条记录和大约 6 个字段。
早些时候,我测试为 Thinking Sphinx 搜索添加 delta 列,但结果却是将整个数据库锁保持了一个小时。之后,当添加文件并尝试重建索引时,这是将数据库锁定保持约 4 小时的查询:
"update user_messages set delta = false where delta = true"
Run Code Online (Sandbox Code Playgroud)
好吧,为了建立服务器,我从 db dump 创建了一个新数据库并将其提升为数据库,以便服务器可以上线。
现在我正在寻找的是在我的表中添加增量列而不锁定表是否可能?一旦delta添加了列,为什么在我运行索引重建命令时会执行上述查询,为什么它会阻塞服务器这么长时间?
PS.:我在 Heroku 上使用 Postgres 和 ika db 模型。
从 Postgres 11 开始,只有易变的默认值仍然需要重写表。手册:
添加具有volatile 的列
DEFAULT或更改现有列的类型将需要重写整个表及其索引。
大胆强调我的。false是不可变的。所以只需添加带有DEFAULT false. 超快,工作完成:
ALTER TABLE tbl ADD column delta boolean DEFAULT false;
Run Code Online (Sandbox Code Playgroud)
DEFAULT添加一个新列而不 DEFAULT或DEFAULT NULL通常不会强制表重写并且非常便宜。仅向其写入实际值会创建新行。但是,引用手册:
添加带有
DEFAULT子句的列或更改现有列的类型将需要重写整个表及其索引。
UPDATE在 PostgreSQL 中写入新版本的行。您的问题没有提供所有信息,但这可能意味着写入数百万个新行。
在执行UPDATE就地操作时,如果表的主要部分受到影响并且您可以以独占方式锁定表,请在执行批量操作之前删除所有索引,然后UPDATE重新创建它们。这种方式更快。手册中的相关建议。
如果您的数据模型和可用磁盘空间允许,则CREATE在后台创建一个新表,然后在一个事务中:DROP旧表和RENAME新表。有关的:
在后台创建新表时:一次将所有更改应用到同一行。重复更新会创建新的行版本并留下死元组。
如果由于约束而无法删除原始表,另一种快速方法是构建一个临时表,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;
Run Code Online (Sandbox Code Playgroud)