如何提高分区(使用继承)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'
以下为解说计划-
没有分区的集群table
分区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
我有以下 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'
以下为解说计划-
没有分区的集群table
分区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