何时在PostgreSQL中使用继承表?

1mrurvl1  于 2023-01-30  发布在  PostgreSQL
关注(0)|答案(8)|浏览(140)

在什么情况下你应该使用继承表?我试着简单地使用它们,继承看起来不像是在OOP世界里。
我以为是这样的:
users具有所有用户级别所需的所有字段。如moderatorsadminsbloggers、等,但字段从父项检查。例如,users具有电子邮件字段,继承的bloggers现在也具有该字段,但它对于usersbloggers而言不是唯一的。即。与我向两个表添加email字段相同。
我能想到的唯一用法是通常使用的字段,如row_is_deletedcreated_atmodified_at。这是继承表的唯一用法吗?

j9per5c4

j9per5c41#

在postgres中使用表继承有一些主要原因。
比如说,我们有一些统计所需的表,这些表是每月创建和填充的:

statistics
    - statistics_2010_04 (inherits statistics)
    - statistics_2010_05 (inherits statistics)

在这个示例中,每个表中有2.000.000行,每个表都有一个CHECK约束,以确保只有匹配月份的数据存储在其中。
那么,是什么让继承成为一个很酷的特性呢?为什么分割数据很酷呢?

  • 性能:选择数据时,我们SELECT * FROM统计WHERE日期BETWEEN x和Y,Postgres只使用有意义的表。例如,SELECT * FROM统计WHERE日期BETWEEN '2010 - 04 - 01'和'2010 - 04 - 15'只扫描表statistics_2010_04,所有其他表都不会被触及-快!
  • 索引大小:我们没有一个大的表和一个大的列日期索引。我们每个月都有一个小的表和小的索引--更快的读取。
  • 维护:我们可以在每个月表上运行vacuumfull、reindex、cluster,而无需锁定所有其他数据

要正确使用表继承来提高性能,请参阅postgresql手册。您需要在每个表上设置CHECK约束,以告知数据库您的数据将在哪个键上进行拆分(分区)。
我大量使用表继承,特别是在按月分组存储日志数据时。提示:如果存储永远不会更改的数据(日志数据),请使用CREATE INDEX ON()WITH(fillfactor = 100)创建或索引;这意味着索引中不会保留更新空间-索引在磁盘上较小。
更新:fillfactor默认值为100,来自http://www.postgresql.org/docs/9.1/static/sql-createtable.html
表的fillfactor是一个介于10和100之间的百分比。缺省值为100(完全打包

ghhaqwfi

ghhaqwfi2#

“表继承”的意思与“类继承”不同,它们的用途也不同。
Postgres是关于数据定义的。有时候是非常复杂的数据定义。OOP(在常见的Java色彩的事物意义上)是关于在单个原子结构中将行为从属于数据定义。“继承”一词的目的和含义在这里有很大的不同。
在OOP领域,我可以定义(这里的语法和语义非常松散):

import life

class Animal(life.Autonomous):
  metabolism = biofunc(alive=True)

  def die(self):
    self.metabolism = False

class Mammal(Animal):
  hair_color = color(foo=bar)

  def gray(self, mate):
    self.hair_color = age_effect('hair', self.age)

class Human(Mammal):
  alcoholic = vice_boolean(baz=balls)

此表可能如下所示:

CREATE TABLE animal
  (name       varchar(20) PRIMARY KEY,
   metabolism boolean NOT NULL);

CREATE TABLE mammal
  (hair_color  varchar(20) REFERENCES hair_color(code) NOT NULL,
   PRIMARY KEY (name))
  INHERITS (animal);

CREATE TABLE human
  (alcoholic  boolean NOT NULL,
   FOREIGN KEY (hair_color) REFERENCES hair_color(code),
   PRIMARY KEY (name))
  INHERITS (mammal);

但是行为在哪里呢?它们不适合任何地方。这不是数据库世界中讨论的“对象”的目的,因为数据库与数据有关,而不是过程代码。您可以在数据库中编写函数来为您进行计算(通常是非常好的主意,但实际上并不适合这种情况)但是函数和方法不是一回事--你所谈论的以OOP形式理解的方法是故意不那么灵活的。
关于作为原理图设备的继承,还有一点需要指出:从Postgres 9.2开始,没有办法同时在所有分区/表族成员之间引用外键约束,您可以编写检查来实现这一点,或者用另一种方法来解决它,但这不是一个内置特性(实际上,这归结为复杂索引的问题,没有人编写过使其自动化所必需的位)。与其为此目的使用表继承,在数据库中,对象继承的一个更好的匹配方法是对表进行示意图扩展。2类似于:

CREATE TABLE animal
  (name       varchar(20) PRIMARY KEY,
   ilk        varchar(20) REFERENCES animal_ilk NOT NULL,
   metabolism boolean NOT NULL);

CREATE TABLE mammal
  (animal      varchar(20) REFERENCES animal PRIMARY KEY,
   ilk         varchar(20) REFERENCES mammal_ilk NOT NULL,
   hair_color  varchar(20) REFERENCES hair_color(code) NOT NULL);

CREATE TABLE human
  (mammal     varchar(20) REFERENCES mammal PRIMARY KEY,
   alcoholic  boolean NOT NULL);

现在,我们有了动物示例的规范引用,可以可靠地将其用作外键引用,并且有了“ilk”列,该列引用xxx_ilk定义表,该表指向扩展数据的“next”表(或者如果同类本身是泛型类型,则指示没有)。编写表函数、视图等等。这类模式是如此容易,以至于当您求助于OOP风格的类继承来创建对象类型族时,大多数ORM框架都在后台执行这类操作。

wmomyfyw

wmomyfyw3#

只要您不需要在父表上创建外键,就可以在OOP范例中使用继承。例如,如果您有一个存储在车辆表中的抽象类车辆和一个从其继承的表汽车,则车辆表中的所有汽车都将可见,但车辆表中司机表的外键将不匹配这些记录。
继承也可以用作partitionning工具,当你的表(日志表等)永远增长时,这一点特别有用。

gudnpqoy

gudnpqoy4#

继承的主要用途是分区,但有时候在其他情况下也很有用。在我的数据库中,有许多表只是外键不同。我的“抽象类”表“image”包含一个“ID”(其主键必须存在于每个表中)和PostGIS 2.0栅格。继承的表(如“site_map”或“artifact_drawing”)具有外键列(“site_name”文本列用于“site_map”,“artifact_id”整数列用于“artifact_drawing”表等)以及主键和外键约束;剩下的部分是从“image”表继承的。2我怀疑将来我可能不得不在所有的image表中添加一个“description”列,所以这可能会保存我相当多的工作,而不会产生真实的的问题(嗯,数据库可能会运行得慢一点)。
编辑:另一个好的用途:使用two-table handling of unregistered users,其他RDBMS在处理这两个表时会有问题,但在PostgreSQL中很容易--当您对继承的“未注册用户”表中的数据不感兴趣时,只需添加ONLY

e0bqpujr

e0bqpujr5#

我对继承表的唯一经验是分区,它工作得很好,但它不是PostgreSQL中最复杂和最容易使用的部分。
上周我们也在研究同样的OOP问题,但是我们在Hibernate上遇到了太多的问题--我们不喜欢我们的设置,所以我们没有在PostgreSQL中使用继承。

8qgya5xd

8qgya5xd6#

当我在表之间有超过1对1的关系时,我使用继承。
示例:假设您要存储具有属性x,y,旋转,缩放的对象贴图位置。
现在假设您有几种不同类型的对象要显示在Map上,并且每个对象都有自己的Map位置参数,并且Map参数永远不会重用。
在这些情况下,表继承对于避免维护非标准化的表或创建位置id并将其交叉引用到其他表非常有用。

tvz2xvvm

tvz2xvvm7#

我尝试了一些操作,我不会指出是否有任何数据库继承的实际用例,但我会给予你一些细节,让你做出决定。https://www.postgresql.org/docs/15/tutorial-inheritance.html您可以尝试下面的SQL脚本。

CREATE TABLE IF NOT EXISTS cities (
  name       text,
  population real,
  elevation  int     -- (in ft)
);

CREATE TABLE IF NOT EXISTS capitals (
  state      char(2) UNIQUE NOT NULL
) INHERITS (cities);

ALTER TABLE cities
ADD test_id varchar(255); -- Both table would contains test col
DROP TABLE cities; -- Cannot drop because capitals depends on it

ALTER TABLE cities
ADD CONSTRAINT fk_test FOREIGN KEY (test_id) REFERENCES sometable (id);

正如你看到我的评论,让我总结一下:

  • 当您添加/删除/更新字段-〉时,继承表也会受到影响
    无法删除父表。
    外键不会继承

从我的Angular 来看,在不断增长的应用程序中,我们无法轻松预测未来的变化,对我来说,我会避免将这应用于早期数据库开发
当特性也是稳定的,并且我们想要创建一些很可能与现有模型相同的数据库模型时,我们可以考虑该用例。

oewdyzsn

oewdyzsn8#

尽可能少地使用它,这通常意味着永远不要使用它,它归结为一种创建违反关系模型的结构的方法,例如,打破信息原则,创建袋子而不是关系。
相反,使用表分区与适当的关系建模相结合,包括进一步的范式。

相关问题