PostgreSQL 表分区
本教程介绍如何使用 PostgreSQL 表分区 与 Bun。
为什么要对表进行分区?
表分区允许将一个大型表拆分成多个较小的表,带来以下好处
- 较小的表在读写方面都更快。
- 您可以非常有效地删除整个分区,而不是逐行删除数据。
- 由于 PostgreSQL 知道如何修剪未使用的分区,因此您可以将分区用作粗略索引。例如,通过按日期对表进行分区,您可能不再需要在日期字段上建立索引,而是可以使用顺序扫描。
- 很少使用的分区可以移动到更便宜的存储中。
分区方法
假设我们有一个表
CREATE TABLE measurements (
id int8 NOT NULL,
value float8 NOT NULL,
date timestamptz NOT NULL
);
您可以通过提供用作 **分区键** 的列来对该表进行分区
CREATE TABLE measurements (
id int8 NOT NULL,
value float8 NOT NULL,
date timestamptz NOT NULL
) PARTITION BY RANGE (date);
PostgreSQL 支持几种分区方法,它们仅在指定分区键行值的方式上有所不同。
按范围分区
按范围分区允许为分区指定一个值范围,例如,我们可以将每个月的数据存储在单独的分区中
CREATE TABLE measurements_y2021m01 PARTITION OF measurements
FOR VALUES FROM ('2021-01-01') TO ('2021-02-01');
按列表分区
列表分区允许为分区指定一个值列表,例如,我们可以将一小部分经常访问的数据存储在热分区中,并将其余数据移动到冷分区中
CREATE TABLE measurements (
id int8 PRIMARY KEY,
value float8 NOT NULL,
date timestamptz NOT NULL,
hot boolean
) PARTITION BY LIST (hot);
CREATE TABLE measurements_hot PARTITION OF measurements
FOR VALUES IN (TRUE);
CREATE TABLE measurements_cold PARTITION OF measurements
FOR VALUES IN (NULL);
然后,您可以通过更新 hot
列在分区之间移动行
-- Move rows to measurements_hot
UPDATE measurements SET hot = TRUE;
-- Move rows to measurements_cold
UPDATE measurements SET hot = NULL;
按哈希分区
按哈希分区允许将行均匀分布到一组表中,例如,我们可以为我们的表创建 3 个分区,并使用哈希和除法的余数为行选择一个分区
CREATE TABLE measurements (
id int8 PRIMARY KEY,
value float8 NOT NULL,
date timestamptz NOT NULL
) PARTITION BY HASH (id);
CREATE TABLE measurements_1 PARTITION OF measurements
FOR VALUES WITH (MODULUS 3, REMAINDER 0);
CREATE TABLE measurements_2 PARTITION OF measurements
FOR VALUES WITH (MODULUS 3, REMAINDER 1);
CREATE TABLE measurements_3 PARTITION OF measurements
FOR VALUES WITH (MODULUS 3, REMAINDER 2);
由于使用了哈希,分区将接收大约相同数量的行。
管理分区
PostgreSQL 允许分离和附加分区
ALTER TABLE measurements DETACH PARTITION measurements_y2021m01;
ALTER TABLE measurements ATTACH PARTITION measurements_y2021m01
FOR VALUES FROM ('2021-01-01') TO ('2021-02-01');
您可以使用这些命令对现有表进行分区,而无需移动任何数据
-- Use the existing table as a partition for the existing data.
ALTER TABLE measurements RENAME TO measurements_y2021m01;
-- Create the partitioned table.
CREATE TABLE measurements (LIKE measurements_y2021m01 INCLUDING DEFAULTS INCLUDING CONSTRAINTS)
PARTITION BY RANGE (date);
-- Attach the existing partition with open left constraint.
ALTER TABLE measurements ATTACH PARTITION measurements_y2021m01
FOR VALUES FROM ('0001-01-01') TO ('2021-02-01');
-- Use proper constraints for new partitions.
CREATE TABLE measurements_y2021m02 PARTITION OF measurements
FOR VALUES FROM ('2021-02-01') TO ('2021-03-01');
使用 Bun 与分区表
Bun 允许创建分区表
type Measure struct {
ID int64
Value float64
Date time.Time
Hot bool `bun:",nullzero"`
}
_, err := db.NewCreateTable().
Model((*Measure)(nil)).
PartitionBy("LIST (hot)").
Exec(ctx)
并使用 ModelTableExpr
直接查询分区
var measures []*Measure
num, err := db.NewSelect(&measures).
ModelTableExpr("measurements_hot").
Count(ctx)
您甚至可以为分区创建单独的模型
type MeasureHot struct {
bun.BaseModel `bun:"measures_hot"`
Measure
}
type MeasureCold struct {
bun.BaseModel `bun:"measures_cold"`
Measure
}
PostgreSQL 监控
要 监控 PostgreSQL,您可以使用 OpenTelemetry PostgreSQL 接收器,它随 OpenTelemetry Collector 提供。
OpenTelemetry Collector 通常用于现代软件应用程序和分布式系统中的监控和可观察性目的。它在从各种来源收集遥测数据、处理这些数据以及将其导出到监控和可观察性后端以进行分析和可视化方面发挥着至关重要的作用。
Uptrace 是一个 Grafana 替代品,它支持分布式跟踪、指标和日志。您可以使用它来监控应用程序并排查问题。
Uptrace 带有一个直观的查询构建器、丰富的仪表板、带有通知的警报规则以及大多数语言和框架的集成。
Uptrace 可以在一台服务器上处理数十亿个跨度和指标,并允许您以低 10 倍的成本监控您的应用程序。