sql - 添加没有表锁的新列?

标签 sql postgresql heroku locking thinking-sphinx

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

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

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

为了搭建服务器,我从 db dump 创建了一个新数据库并将其提升为数据库,这样服务器就可以上线了。

现在我正在寻找的是在没有表锁的情况下在我的表中添加增量列是可能的吗?添加 delta 列后,为什么在我运行索引重建命令时会执行上述查询,为什么它会阻塞服务器这么长时间?

PS.: 我在 Heroku 上使用 Postgres 和 ika 数据库模型。

最佳答案

Postgres 11 或更高版本

从 Postgres 11 开始,只有易变的默认值仍然需要重写表。 The manual:

Adding a column with a volatile DEFAULT or changing the type of an existing column will require the entire table and its indexes to be rewritten.

大胆强调我的。 false 是不可变的。所以只需添加带有 DEFAULT false 的列。超快,完成工作:

ALTER TABLE tbl ADD column delta boolean DEFAULT false;

Postgres 10 或更早版本,或用于 volatile DEFAULT

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

Adding a column with a DEFAULT clause or changing the type of an existing column will require the entire table and its indexes to be rewritten.

PostgreSQL 中的

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

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

如果您的数据模型和可用磁盘空间允许,在后台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;

关于sql - 添加没有表锁的新列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10412078/

相关文章:

postgresql - 您如何有效地确定 Postgres 表是否有行

将代码推送到服务器时出现 Heroku 问题

node.js - 引用错误: process is not defined, Node ,Heroku

heroku - Ionic PWA 部署

sql - 将总计添加到交叉表查询中的透视列的 SUM 中

mysql - 预定数据库作业的可扩展性

sql - Azure SQL 数据库防火墙是否自动允许虚拟机位于同一资源组中?

sql - "WHERE 1 IN"SQL 中的子句

django - 不存在 : object matching query does not exist

postgresql - 将数据插入 Postgresql 的存储过程