如何提高分区(使用继承)PostgreSQL table 的读取性能,超过相同版本的集群 table 约 50M 行

How to improve read performance on a partitioned (using inheritance) PostgreSQL table over the same version of clustered table with ~50M rows

我有以下 tables 用于在我的 PostgreSQL 12 实例中存储时间序列指标数据 -

 CREATE TABLE metric_values
(
    event_id bigint NOT NULL,
    "timestamp" timestamp without time zone NOT NULL,
    value numeric(20,4) NOT NULL
)

CREATE TABLE metric_values_old
(
    event_id bigint NOT NULL,
    "timestamp" timestamp without time zone NOT NULL,
    value numeric(20,4) NOT NULL
)

这两个 table 与 event_id 和时间戳列上的索引相同。不同之处在于 metric_values_old 有 ~50M 行并基于上述索引进行聚类,而 metric_values 通过继承进行分区,在每个 child.[=19 上创建单独的索引和聚类=]

每个分区应该保存 1 年的数据,从时间戳列派生。

这里是 child tables -

的定义
CREATE TABLE metric_values_2021
(
    -- Inherited from table metric_values: event_id bigint NOT NULL,
    -- Inherited from table metric_values: "timestamp" timestamp without time zone NOT NULL,
    -- Inherited from table metric_values: value numeric(20,4) NOT NULL,
    CONSTRAINT metric_values_2021_event_id_timestamp_key UNIQUE (event_id, "timestamp"),
    CONSTRAINT metric_values_2021_timestamp_check CHECK (date_part('year'::text, "timestamp") = 2021)
)
    INHERITS (metric_values)
TABLESPACE pg_default;

CREATE INDEX metric_values_2021_idx
    ON metric_values_2021 USING btree
    (event_id ASC NULLS LAST, "timestamp" ASC NULLS LAST)
    TABLESPACE pg_default;

ALTER TABLE metric_values_2021
    CLUSTER ON metric_values_2021_idx;

但是在比较这两个 table 的查询性能时,分区 table 的性能比集群 table 差。我期望性能会更好,因为查询具有时间戳条件,并且能够从特定的 child 中检索。我更愿意使用分区,因为这样更容易维护,并且每个 child table 将具有固定大小,这与具有 50M 行并不断增长的集群 table 不同。

以下是我在 tables -

上尝试的查询
select event_id, timestamp, value from metric_values
WHERE timestamp between '2020-08-01' and '2020-08-31'

select event_id, timestamp, value from metric_values_old
WHERE timestamp between '2020-08-01' and '2020-08-31'

以下为解说计划-

  1. 没有分区的集群table

  2. 分区Table

分区的 table 似乎正在扫描所有分区,因此成本增加。任何关于改进此性能的建议将不胜感激。谢谢!

遵循@a_horse_with_no_name 的建议并能够解决查询问题 -

select event_id, timestamp, value from metric_values
WHERE timestamp between '2020-08-01' and '2020-08-31'

虽然性能更好,但 PostgreSQL 似乎仍然扫描所有分区。如果有人知道原因或者有办法避免这种情况,请告诉我。非常感谢您的帮助。

问题已通过从继承方法更改为声明方法得到解决。请参考这里@a_horse_with_no_name建议的解决方案-https://dbfiddle.uk/?rdbms=postgres_13&fiddle=f99f23409e416be31f5bad493083196b