PostgreSQL 是一个对象关系数据库管理系统(object-relational database management system),如果你看维基百科的定义,ORDBMS 是一种拥有面向对象特性的关系型数据库,对象、类、继承(Inheritance)等概念直接在数据库 schema 和查询语言层面支持。

An object–relational database (ORD), or object–relational database management system (ORDBMS), is a database management system (DBMS) similar to a relational database, but with an object-oriented database model: objects, classes and inheritance are directly supported in database schemas and in the query language.

一定会有人认为 Inheritance 是 PostgreSQL 被称为 ORDBMS 的主要原因,比如 David Johnston(PG contributor) 在 slack 上的回复:

ORDBMS

但 PostgreSQL 社区维护的 Don’t Do This 里提示了 Don’t use table inheritance,所以 Inheritance 一定不是 PostgreSQL 称作 ORDBMS 的唯一原因。ChatGPT 给出的答案我认为具有一定参考价值:

PostgreSQL Object Meaning

为什么不建议用 Table Inheritance

我们来看一个 PostgreSQL 邮件列表中出现过的例子:

CREATE TABLE PERSON (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    dob DATE
);

CREATE TABLE CUSTOMER (
    registration_date DATE NOT NULL,
    contact VARCHAR(255)
) INHERITS (person);

INSERT INTO PERSON VALUES (1, 'Fulano', '1965-06-07');
INSERT INTO CUSTOMER VALUES (2, 'Beltrano', '1980-10-07', '2023-10-10', '5561999999999');

创建一个父表 PERSON,id 为主键,子表 CUSTOMER 继承 PERSON,两张表各插入一条记录。如果现在我们向 CUSTOMER 插入一条数据,能成功吗?

INSERT INTO CUSTOMER (id, name, dob, registration_date, contact)
SELECT id, name, dob, '2023-10-17', 'contact@example.com'
FROM person
WHERE id = 1;

答案是可以。查询父表得出的结果:

postgres=# select * from person;
 id |   name   |    dob
----+----------+------------
  1 | Fulano   | 1965-06-07
  2 | Beltrano | 1980-10-07
  1 | Fulano   | 1965-06-07
(3 rows)

这难道不是主键冲突了吗?

父表和子表都存储了数据,父表只检查自身的约束(Constraints),子表的插入不会去检测父表上定义的约束。对父表的查询会把父表和子表的数据合并输出,从其查询计划可以看出代价估算也不准确。

postgres=# explain select * from person;
                                QUERY PLAN
---------------------------------------------------------------------------
 Append  (cost=0.00..12.26 rows=84 width=524)
   ->  Seq Scan on person person_1  (cost=0.00..1.14 rows=14 width=524)
   ->  Seq Scan on customer person_2  (cost=0.00..10.70 rows=70 width=524)
(3 rows)

以上可能就是不建议使用 Table Inheritance 的主要原因,在分区表特性逐渐完善之后,Table Inheritance 特性在未来极有可能被删除:

inheritance probably would have been removed

如果你在考虑使用 Table Inheritance,请先评估一下 Table Partitioning 是否能解决你的问题,可能会减少一些不必要的麻烦。