何时使用PostgreSQL中的inheritance表?
在哪种情况下你应该使用inheritance的表? 我试图很简单地使用它们,并且在OOP世界中看起来并不像。
我认为它是这样工作的:
表users
具有所有用户级别所需的所有字段。 moderators
, admins
, bloggers
等表格,但不从父母检查。 例如, users
具有电子邮件字段,而且inheritance的bloggers
也有它,但同时对于users
和bloggers
,这不是唯一的。 即。 与我向两个表中添加电子邮件字段相同。
只有我能想到的用法是通常使用的字段,比如row_is_deleted , created_at , modified_at 。 这是inheritance表的唯一用法吗?
在postgres中使用表inheritance有一些主要原因。
比方说,我们有一些统计表所需的表格,这些表格是每月创build和填写的:
statistics - statistics_2010_04 (inherits statistics) - statistics_2010_05 (inherits statistics)
在这个例子中,我们在每个表中有2.000.000行。 每个表都有一个CHECK约束,以确保只有匹配的月份的数据存储在其中。
那么是什么让inheritance成为一个很酷的function – 为什么分裂数据很酷?
- 性能:在select数据时,我们select* FROM统计信息,其中x和y之间的date在哪里,而Postgres只使用这些表,这是有意义的。 例如。 SELECT * FROM统计信息WHERE date between'2010-04-01'AND'2010-04-15'只扫描表statistics_2010_04,所有其他表将不会被触及 – 快!
- 索引大小:在列date我们没有胖胖的大胖子。 我们每月都有小桌子,小指数 – 更快的读数。
- 维护:我们可以在每个月表上运行vacuum full,reindex,cluster而不locking所有其他数据
要正确使用表inheritance作为性能增强器,请查看postgresql手册。 您需要在每个表上设置CHECK约束来告诉数据库,数据在哪个键上被分割(分区)。
我大量使用表inheritance,尤其是当存储按月分组的日志数据时。 提示:如果你存储的数据永远不会改变(日志数据),用CREATE INDEX ON()WITH(fillfactor = 100)创build或索引。 这意味着索引中不会保留更新空间 – 索引在磁盘上较小。
更新:fillfactor默认为100,从http://www.postgresql.org/docs/9.1/static/sql-createtable.html :
表的填充因子是10到100之间的百分比.100(完整填充)是默认值
“表inheritance” 是指与“类inheritance”不同的东西,它们用于不同的目的。
Postgres是关于数据定义的。 有时非常复杂的数据定义。 OOP(在普通的Java颜色的事物中)是关于将行为从属于单一primefaces结构中的数据定义。 “inheritance”这个词的目的和意义在这里有很大的不同。
在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);
但行为在哪里? 他们不适合任何地方。 这不是数据库世界中讨论的“对象”的目的,因为数据库涉及数据而不是程序代码。 你可以在数据库中编写函数来为你做计算(通常是一个非常好的主意,但并不是真正适合这种情况的东西),但是函数和方法不是一回事 – 你正在谈论的OOPforms的方法关于故意不太灵活。
关于作为电路设备的inheritance,还有一点需要指出:从Postgres 9.2开始,无法一次引用所有分区/表族成员的外键约束。 你可以编写检查来完成这个工作,也可以用另一种方式绕过它,但它不是一个内置的特性(这归结于复杂索引的问题,实际上没有人编写必要的位来实现自动化)。 为了达到这个目的,不是使用表inheritance,而是在数据库中更好地匹配对象inheritance,即对表进行扩展。 像这样的东西:
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”表或者表示没有,如果这是genericstypes本身)。 对这种模式编写表函数,视图等非常容易,大多数ORM框架在使用OOP风格的类inheritance来创build对象types系列时在后台完成这种事情。
只要您不需要在父表上创build外键,就可以在OOP范例中使用inheritance。 举个例子,如果你有一个抽象类的车辆存储在一个车辆的桌子和一个从它inheritance的台车,所有的车辆将在车辆表中可见,但车辆表上的驾驶台的外键将不匹配这些logging。
inheritance也可以用作分区工具。 当你想要永久增长的表(日志表等)时,这是特别有用的。
inheritance的主要用途是分区,但有时在其他情况下也是有用的。 在我的数据库中有许多表只有一个外键不同。 我的“抽象类”表“图像”包含一个“ID”(主键必须在每个表中)和PostGIS 2.0栅格。 诸如“site_map”或“artifact_drawing”的inheritance表具有“site_map”的“site_name”文本列,“artifact_drawing”表的“artifact_id”整数列等)以及主键和外键约束; 剩下的就是从“图像”表inheritance下来的。 我怀疑我将来可能需要在所有图像表中添加一个“描述”列,这样可以为我节省大量工作,而不会造成实际问题(数据库可能运行得慢一些)。
编辑:另一个很好的用途:与两个表处理未注册的用户 ,其他RDBMSs处理两个表时遇到问题,但在PostgreSQL中很容易 – 只是当你没有被捕获的数据在inheritance的“未注册用户”表。
我对inheritance表的唯一经验是分区。 它工作正常,但它不是PostgreSQL最复杂和最易于使用的部分。
上个星期我们看到了相同的OOP问题,但是我们有太多的Hibernate问题(不喜欢我们的设置),所以我们没有在PostgreSQL中使用inheritance。
我写了一篇关于如何在多态性问题中使用PostgreSQLinheritance的博客文章,以便您可以编写单个数据库函数来更新不同子表中的inheritance字段。 我还展示了数据库如何在后台处理这个function,并展示解决性能问题的方法:
尽可能less地使用它。 而这通常意味着永远不会,这就是创build违反关系模型的结构的一种方式,例如通过违反信息原则并创build包而不是关系。