PostgreSQL 内置分区功能

作者:Rock Zhang

分区是指将一个逻辑上大的表拆分为较小的物理块。主分区表不存储任何数据,数据存储在各个子分区表中。主表与分区表属于一对多的关系,这些子表继承并属于一个主表。

分区可以提供以下好处:

  • 在某些情况下,尤其是当表中大多数被频繁访问的行位於单个分区或少量分区中时,查询性能可以得到显着提高。分区减小了索引的大小,并使索引中频繁使用的部分更有可能装入内存。

  • 当查询或更新访问单个分区的很大一部分时,可以通过对该分区进行顺序扫描而不是使用索引和分散在整个表中的随机访问读取来提高性能。

  • 可以通过添加或删除分区来完成批量加载和删除。使用ALTER TABLE DETACH PARTITION或DROP TABLE进行删除单个分区比批量操作要快得多。这些命令还完全避免了由批量DELETE引起的VACUUM开销。

  • 很少使用的数据可以迁移到更便宜、更慢的存储介质上。

通常只有在表很大的情况下,这些好处才是值得的。表可以从分区中受益的确切时间取决于应用程序,尽管经验法则是表的大小应超过数据库服务器的物理内存。

PostgreSQL 10 以后的版本为分区提供内置支持:

1 范围分区(PARTITION BY RANGE)
该表被划分为由键列或列集定义的“范围”,分配给不同分区的值的范围之间没有重叠。例如,可以按日期范围或特定业务对象的标识符范围进行分区。

2 列表分区(PARTITION BY LIST)
通过显式列出哪些键值出现在每个分区中来对表进行分区。

列表分区的实例

某系统的一张表含有来自企业内部和企业外部不同数据源的数据,用字段is_inner来标识数据来源,当is_inner=True时,数据来自内部, 反正来自外部。系统更多的情况会对来自内部和外部的数据分别经行管理,将数据集根据来源切分成两张表可以明显提高查询性能,和减少表的维护成本。

  1. 创建分区表(主表), 声明为列表分区, 这里没有主键和索引。

CREATE TABLE IF NOT EXISTS dv (
    id        serial,
    d1        int,
    d2        int,
    d3        int,
    is_inner  bool not null
) PARTITION BY LIST(is_inner);

2 分别创建分区(子表),声明各自的数据范围

CREATE TABLE dv_inner PARTITION OF dv
    FOR VALUES IN (True);

CREATE TABLE dv_outer PARTITION OF dv
    FOR VALUES IN (False);

3 为每个分区(子表)创建索引


CREATE INDEX ON dv_inner (id);
CREATE INDEX ON dv_outer (id);

至此已经完成分区表的创建。

下面插入一些数据并查询

insert into dv (d1,d2,d3,is_inner) values (1,1,1, True);
insert into dv (d1,d2,d3,is_inner) values (2,2,2, False);

查询所有分区的数据

select * from dv;

查询单个分区的数据

select * from dv_inner;
select * from dv_outer;

内置分区的约束

  • 没有可用于在所有分区上自动创建匹配索引的工具。必须使用单独的命令将索引添加到每个分区。这也意味着无法创建跨越所有分区的主键,唯一约束或排除约束。只能单独约束每个子分区。

  • 由于分区表不支持主键,因此不支持引用分区表的外键,也不支持从分区表到其他表的外键引用。

  • 将ON CONFLICT子句与分区表一起使用会导致错误,因为唯一约束或排除约束只能在单个分区上创建。不支持在整个分区层次结构中强制执行唯一性(或排除约束)。

  • 导致行从一个分区移动到另一个分区的UPDATE失败,因为该行的新值不能满足原始分区的隐式分区约束。

  • 如果需要,行触发器必须在单个分区上定义,而不是在分区表上定义。

  • 不允许在同一分区树中混合临时和永久关系。因此,如果分区表是永久性的,则分区也必须是永久性的,分区表是临时的也是如此。使用临时关系时,分区树的所有成员必须来自同一会话。
    义。

  • 不允许在同一分区树中混合临时和永久关系。因此,如果分区表是永久性的,则分区也必须是永久性的,分区表是临时的也是如此。使用临时关系时,分区树的所有成员必须来自同一会话。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章