Postgres 使用主键分区

问题描述 投票:0回答:1

我有一个大数据库,它代表一个图表,其中包含大量不断增长的数据。 数据库看起来类似

CREATE TABLE node (
  id BIGSERIAL PRIMARY KEY,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  status TEXT NOT NULL DEFAULT 'new',
  -- ... other columns ...
  data JSONB
);

CREATE TABLE edge (
  parent BIGINT REFERENCES node(id),
  child BIGINT REFERENCES node(id)
);

-- ...
-- a few other tables with foreign keys to node
-- ...

现在我的数据库中有大量数据,某些查询开始陷入相当多的困境,因此我希望能够将我想要“存档”的节点移动到一个单独的表分区,而该分区不会得到阅读任何对时间敏感的查询。不过,我仍然可以轻松查询它们以进行历史分析。

理想情况下,我会在我的

archived BOOL NOT NULL DEFAULT false
表中添加一个
node
列,然后将其更改为
PARTITION BY LIST (archived)

不幸的是,Postgres 分区不允许我对

node.id
有唯一性约束,如果没有唯一性约束,我就无法在我的
REFERENCES
表中使用外键
edge

我可以删除

REFERENCES
外键关系,然后危险地生活,但我真的不喜欢那样。

我尝试添加

archived
列并在其上构建
BRIN
索引,但 Postgres 拒绝使用它。 我想我可以
CLUSTER node USING archived_idx
但要找到所需的
ACCESS EXCLUSIVE
锁的停机时间会很困难。

对于需要外键的表,是否有其他策略来对数据(或类似的策略)进行分区?

database postgresql partitioning data-partitioning
1个回答
0
投票

首先,4000万条记录本身并不算多。然而,当这些 JSON 对象很大或者大多数数据已经存档时,它可能会成为一种负担。

您可以通过在分区上而不是在父分区上生成主键来改进这一点:

CREATE TABLE node
(
    id         BIGINT GENERATED ALWAYS AS IDENTITY, -- use an identity
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    status     TEXT        NOT NULL DEFAULT 'new',
    archived   BOOLEAN     NOT NULL DEFAULT FALSE,
    -- ... other columns ...
    data       JSONB
) PARTITION BY LIST (archived);

CREATE TABLE node_current PARTITION OF node
    (
        CONSTRAINT pkey_node_current
            PRIMARY KEY (id)
        )
    FOR VALUES IN (FALSE);

CREATE TABLE node_archived PARTITION OF node
    (
        CONSTRAINT pkey_node_archived
            PRIMARY KEY (id)
        )
    FOR VALUES IN (TRUE);

CREATE TABLE edge
(
    parent BIGINT REFERENCES node_current (id),
    child  BIGINT REFERENCES node_current (id)
);

如果您进行更新,还有其他更好的解决方案可以跟踪记录的不同版本。但这取决于您的要求。

© www.soinside.com 2019 - 2024. All rights reserved.