PostgreSQL 的表继承与分区

一、PostgreSQL 的表继承

PostgreSQL 的表继承(Inheritance)允许一个表"继承"另一个表的结构和约束,就像子类继承父类的属性一样。

换句话说,子表会自动拥有父表的所有列定义(字段),并且可以新增自己的字段。同时,查询父表时,也可以选择是否自动包含子表中的数据。

其基本语法如下:

sql 复制代码
CREATE TABLE 子表 (
    子表自有字段 数据类型,
    ...
) INHERITS (父表);

表继承示例

假设我们有一个电商平台,商品分为三类:

  • 普通商品(normal_product)
  • 电子商品(digital_product)
  • 生鲜商品(fresh_product)

三者都共有基础字段:id, name, price,但子类商品有各自特有的属性。

定义父表(通用商品表)

sql 复制代码
CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    price NUMERIC(10, 2) NOT NULL,
    created_at TIMESTAMP DEFAULT now()
);

父表定义所有商品的公共字段。

定义子表(继承父表)

sql 复制代码
-- 电子商品表
CREATE TABLE digital_products (
    file_size_mb INT,
    download_url TEXT
) INHERITS (products);

-- 生鲜商品表
CREATE TABLE fresh_products (
    expiration_date DATE,
    storage_temp TEXT
) INHERITS (products);

每个子表通过 INHERITS (products) 继承父表字段。

插入数据

sql 复制代码
INSERT INTO products (name, price) VALUES ('普通鼠标', 39.9);

INSERT INTO digital_products (name, price, file_size_mb, download_url)
VALUES ('课程:PostgreSQL指南', 99.0, 512, 'https://example.com/pg-course');

INSERT INTO fresh_products (name, price, expiration_date, storage_temp)
VALUES ('火龙果', 5.5, '2025-11-10', '0-5°C');

查询数据

(1)查询父表(默认包含子表数据)

sql 复制代码
SELECT id, name, price, created_at FROM products;

结果包含所有三类商品:

(2)只查询父表自身数据

sql 复制代码
SELECT * FROM ONLY products;

仅返回普通商品(不含继承表)。

查看继承关系

sql 复制代码
\d+ products

继承的特性与限制

  • 数据隔离:子表的数据物理上存储在自己的表空间中,与父表分离。
  • 约束继承 :CHECK约束会被子表继承,但主键、外键、唯一约束和索引不会自动继承。
  • 多表继承:一个表可以同时继承多个父表(多继承),继承所有父表的列。

继承的典型应用场景

  • 商品分类存储:将不同类别的商品(如电子产品、服装、图书)存储在不同的子表中,但通过 products 父表统一查询所有商品。
  • 权限管理:为不同类别的商品表设置不同的访问权限,同时保持统一的查询接口。
  • 逻辑分组:在应用层实现多态行为,如不同类型的"商品"共享基础字段

二、PostgreSQL表分区

随着数据量的增长,单表性能会成为瓶颈。从 PostgreSQL10 开始引入表分区,专为性能和可维护性设计,它将一个大表逻辑上分为多个子表(分区),但对外表现为单一表,极大提升了查询性能和管理效率。

分区类型

PostgreSQL 当前主要支持四种分区类型,每种类型适用于不同的业务场景:

分区类型 定义关键字 说明 常见应用场景
范围分区(Range) PARTITION BY RANGE(column) 按某个列的值范围(区间)划分数据 按时间、ID、价格等连续字段分表,如日志表、订单表
列表分区(List ) PARTITION BY LIST(column) 按枚举值列表划分数据 按国家、地区、商品类型等分类,如按国家分库
哈希分区(Hash) PARTITION BY HASH(column) 通过哈希函数对列进行取模划分 数据分布均匀、负载均衡的场景,如用户ID分区
复合分区(Subpartitioning) 嵌套定义(如 PARTITION BY RANGE + PARTITION BY LIST 在一级分区的基础上再细分子分区 大型系统中的层级分区,如时间 + 地区双维度划分

分区示例(RANGE )

例如我们可以按商品上架年份进行分区。

定义分区表(主表)

sql 复制代码
CREATE TABLE products_partitioned (
    id BIGINT GENERATED ALWAYS AS IDENTITY,
    name TEXT NOT NULL,
    price NUMERIC(10,2) NOT NULL,
    created_at DATE NOT NULL,
    PRIMARY KEY (id, created_at)   -- 注意:包含了分区键 created_at
) PARTITION BY RANGE (created_at);

创建各个分区表

sql 复制代码
CREATE TABLE products_2024 PARTITION OF products_partitioned
  FOR VALUES FROM ('2024-01-01') TO ('2025-01-01');

CREATE TABLE products_2025 PARTITION OF products_partitioned
  FOR VALUES FROM ('2025-01-01') TO ('2026-01-01');

插入数据(自动路由)

sql 复制代码
INSERT INTO products_partitioned (name, price, created_at)
VALUES ('电动牙刷', 199.0, '2024-06-01');

INSERT INTO products_partitioned (name, price, created_at)
VALUES ('蓝牙耳机', 299.0, '2025-03-15');

查询与优化

sql 复制代码
SELECT * FROM products_partitioned WHERE created_at >= '2025-01-01';

查看分区结构

shell 复制代码
\d+ products_partitioned

你会看到类似输出:

bash 复制代码
Partition key: RANGE (created_at)
Indexes:
    "products_partitioned_pkey" PRIMARY KEY, btree (id, created_at)
Partitions: products_2024 FOR VALUES FROM ('2024-01-01') TO ('2025-01-01'),
            products_2025 FOR VALUES FROM ('2025-01-01') TO ('2026-01-01')

说明

在PostgreSQL中,分区表的主键或唯一约束必须包含所有分区键列,否则会出现:

sql 复制代码
ERROR: unique constraint on partitioned table must include all partitioning columns

三、继承VS分区:区别总结

对比维度 表继承(Inheritance) 表分区(Partitioning)
设计目的 逻辑数据模型扩展 性能优化与数据管理
定义语法 INHERITS PARTITION BY
查询行为 父表聚合所有子表 自动分区路由
约束继承 不会自动继承 系统自动管理
主键要求 可独立定义 必须包含分区列
应用场景 业务类型区分 大表按时间/范围拆分

使用建议总结:

如果你是为了"性能"和"可维护性"拆分数据 → 用分区;

如果是为了"逻辑建模"或"多态"而组织数据 → 才考虑继承(但需谨慎,维护成本高,易出错)。

相关推荐
金仓拾光集4 小时前
国产化转型实战:制造业供应链物流系统从MongoDB至金仓数据库迁移全指南
数据库·mongodb·数据库平替用金仓·金仓数据库
天天进步20155 小时前
Django vs Flask:2025年该如何选择Python Web框架?
数据库·sqlite
JavaTree20175 小时前
【MySQL】mysqldump使用方法
数据库·mysql
HC02205 小时前
【保姆级教程】MySQL 5.7 彻底卸载与重新安装全流程(附常见问题解决)
数据库·mysql·mysql5.7·数据库安装·彻底卸载 mysql·mysql 配置教程
lkforce5 小时前
mysql表连接,因类型不匹配而导致索引失效的场景
数据库·mysql
超人小子5 小时前
mysql重置密码
数据库·mysql·adb
普通网友5 小时前
【mysql】锁机制 - 2.行锁间隙锁临键锁
数据库·mysql
zwtahql5 小时前
mysql的安装和卸载过程
数据库·mysql
零起飞5 小时前
生产管理系统详解:高离散制造 – 生产订单数据库设计表(核心表结构)
数据库·oracle·制造