如何安全地重新索引postgres上的主键?

时间:2019-01-27 10:21:25

标签: postgresql

我们有一个巨大的表,其中包含主键索引上的膨胀。我们不断在该表上存档旧记录。

我们通过同时创建索引并删除旧索引来重新索引其他列。这是为了避免干扰生产流量。 但这对于主键是不可能的,因为有依赖于它的外键。至少基于我们的尝试。

在不阻止表上DML语句的情况下安全地重新索引主键的正确方法是什么?

3 个答案:

答案 0 :(得分:1)

您可以为此使用pg_repack。

pg_repack是PostgreSQL的一个扩展,可让您从表和索引中删除膨胀,并有选择地恢复聚簇索引的物理顺序。

在整个过程中,它不持有排他锁。它仍然会执行一些锁定,但这应该只在短时间内。您可以在此处查看详细信息:https://reorg.github.io/pg_repack/

要对索引执行重新打包,您可以尝试:

pg_repack -t table_name --only-indexes

答案 1 :(得分:0)

TL; DR

仅使用其索引名称reindex作为其他索引:

REINDEX INDEX <indexname>;

MCVE

让我们创建一个具有主键约束的表,该约束也是一个索引:

CREATE TABLE test(
    Id BIGSERIAL PRIMARY KEY
);

在目录中,我们看到约束名称:

SELECT conname FROM pg_constraint WHERE conname LIKE 'test%';
-- "test_pkey"

有了索引的名称,我们可以对其重新索引:

REINDEX INDEX test_pkey;

您还可以在创建时修复约束名称:

CREATE TABLE test(
    Id BIGSERIAL NOT NULL
);
ALTER TABLE test ADD CONSTRAINT myconstraint PRIMARY KEY(Id);

如果必须解决并发问题,请使用建议的方法a_horse_with_no_name create a unique index concurrently

-- Ensure Uniqueness while recreating the Primary Key:
CREATE UNIQUE INDEX CONCURRENTLY tempindex ON test USING btree(Id);
-- Drop PK:
ALTER TABLE test DROP CONSTRAINT myconstraint;
-- Recreate PK:
ALTER TABLE test ADD CONSTRAINT myconstraint PRIMARY KEY(Id);
-- Drop redundant Index:
DROP INDEX tempindex;

要检查索引是否存在:

SELECT * FROM pg_index WHERE indexrelid::regclass = 'tempindex'::regclass

答案 2 :(得分:0)

REINDEX CONCURRENTLY 似乎也有效。我在我的数据库上试了一下,没有出现任何错误。

REINDEX INDEX CONCURRENTLY <indexname>;

我认为它可能与@jlandercy 在他的回答中描述的类似。在重新索引运行时,我看到一个带有后缀 _ccnew 的索引,并且现有的索引也完好无损。最终,我猜想在删除旧索引后,该索引被重命名为原始索引,并且我最终在我的表上看到了一个唯一的主索引。

我正在使用 postgres v12.7