本文来源:www.codacy.com/blog/how-to…
在Postgres中更新大型表并不像看起来那样简单。如果您的表包含数亿行,您将发现很难及时进行简单的操作,例如添加列或更改列类型。
在不停机的情况下进行这类操作是一个更大的挑战。在这篇博客文章中,我将尝试概述一些策略,以在管理大型数据集的同时最大程度地减少表不可用性。
当您更新列中的值时,Postgres将在磁盘中写入一个新行,弃用旧行,然后继续更新所有索引。此过程等同于INSERT
加上每一行后再DELETE
,这会占用大量资源。
除此之外,需要更新大表时还应了解的事项列表:
考虑到这一点,让我们看一些可以用来有效更新表中大量数据行的策略:
如果您可以使用例如顺序ID对数据进行细分,则可以批量更新行。由于您只需要保持较短时间的锁定,因此可以最大化表的可用性。如果添加新列,则可以将其临时设置为可为空,然后开始逐渐用新值填充它。
这种方法的主要问题是性能,这是一个非常缓慢的过程,因为就地更新成本很高。在迁移期间,它可能还需要更复杂的应用程序逻辑。
更新大表的最快方法是创建一个新表。
如果可以安全地删除现有表,并且有足够的磁盘空间,则执行更新的最简单方法是将数据插入到新表中,然后对其进行重命名。以下是此操作的基本执行脚本:
create table user_info_copy (LIKE user_info INCLUDING INDEXES INCLUDING COMMENTS);
INSERT INTO user_info_copy
SELECT user_no, idcard_no, real_name, bankcard_no, bind_mobile
, false, bind_status, user_identity, create_time, creator
, edit_time, editor, is_del, VERSION, customer_id
, id_card_type, source_id, platform_no, one_passport_no, bank_code
FROM user_info;
drop TABLE user_info;
alter table user_info_copy rename to user_info;
如果由于不想重新创建视图或由于其他限制而不能删除原始表,则可以使用临时表保存新值,截断旧表并在那里重写数据。当您有未决的写请求时,此方法也有一些优点,如我们将在下一部分中看到的。
如果您的表可以容纳在内存中,则应在此事务期间增加temp_buffers
属性。使用RAM代替磁盘来存储临时表将明显提高性能:
SET temp_buffers = 3000MB; ----相应地更改此值
# 创建临时表
CREATE TABLE temp_user_info(
user_no BIGINT,
PRIMARY KEY( user_no )
);
# 如果需要提速可以从表中删除索引
# 复制数据到临时表中
insert into temp_user_info select user_no from user_info;
# 改变表结构,比如需要添加新列
TRUNCATE user_no;
# 执行插入列字段语句
# 再把数据反写到user_info表
即使进行了上述优化,重新创建表仍然是缓慢的操作。如果您正在实时数据库中运行查询,则可能需要处理并发写入请求。
最简单的方法是在事务期间在表上强制使用SHARE LOCK
, 语句如下
LOCK TABLE user_info IN SHARE MODE;
如果花费太长时间,所有写请求将一直等到锁释放或超时为止。如果未删除原始表,则一旦事务结束,将执行未超时的请求。请注意,即使使用相同的名称创建新表,请求仍将失败,因为它们使用表OID。
根据写请求的性质,您还可以创建自定义规则来存储对表所做的更改。例如,您可以设置一个规则,以在开始数据迁移之前记录已删除的行:
CREATE RULE deleted_rule AS ON DELETE
TO tbl
DO INSERT INTO tbl_deletes VALUES
(
OLD.id
);
迁移结束时,您只需从tbl_deletes中读取ID,然后在新表上将其删除。可以使用类似的方法来处理其他类型的请求。
一旦达到一定大小,曾经瞬时的操作可能需要几个小时来准备和执行。个人实验结论:
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有