继承指的是表的继承,就是一个表继承自另一个表,字段也继承自父表,跟面向对象的概念差不多。因为有时候几张表就是具有差不多的属性或字段,唯一有区别的就是其中一两个字段,这个时候可以用继承来简化操作和管理。

比如,如果不用继承,会像下面这样处理的。

要查找那两张表就得使用union语句。

而使用继承就是这样处理的。

  1. name text,
  2. population real,
  3. altitude int -- (in ft)
  4. );
  5. CREATE TABLE capitals (
  6. state char(2)
  7. ) INHERITS (cities);

这样就创建了两张表,插入(insert)数据之后就可以用select来查询的。

分区是数据库的一种设计实现方法。我们知道,当一张表的数据越来越多时,假如到了上亿条或几十亿条记录,对这张表的操作都会比较慢,比如,查询,更改等。而分区技术就是把这一张大表分成几个逻辑分片。分区之后有很多好处:

  • 单个分区表的索引和表都变小了,可以保持在内存里面,适合把热数据从大表拆分出来的场景;
  • 对于大范围的查询,大表可以通过索引来避免全表扫描,但是如果分区的话,可以使用分区的全表扫描;
  • 大批量的数据导入或删除,删除大量的数据使用DELETE会很慢,可是如果使用分区表,直接drop或truncate整个分区表即可;

而分区技术就是基于上面所提的继承技术来实现的。

PostgreSQL实现了两种分区。

  • Range Partitioning:比如数值范围,时间范围等。
  • List Partitioning: 按照固定的值。

其中一种实现分区的方法是基于继承并配合触发器来实现。

先创建母表,它其实是一张只有数据结构的表。

  1. CREATE TABLE measurement_y2006m02 (
  2. CHECK ( logdate >= DATE '2006-02-01' AND logdate < DATE '2006-03-01' )
  3. ) INHERITS (measurement);
  4. CHECK ( logdate >= DATE '2006-03-01' AND logdate < DATE '2006-04-01' )
  5. ) INHERITS (measurement);
  6. ...
  7. CREATE TABLE measurement_y2007m11 (
  8. ) INHERITS (measurement);
  9. CREATE TABLE measurement_y2007m12 (
  10. CHECK ( logdate >= DATE '2007-12-01' AND logdate < DATE '2008-01-01' )
  11. ) INHERITS (measurement);
  12. CREATE TABLE measurement_y2008m01 (
  13. CHECK ( logdate >= DATE '2008-01-01' AND logdate < DATE '2008-02-01' )
  14. ) INHERITS (measurement);

check指定的是约束条件,按照时间来规定范围。

按照需要可以添加索引。

当执行INSERT INTO measurement ...时,为了让数据插入到正确的分区表上,我们需要创建触发器来实现这个逻辑。

  1. CREATE OR REPLACE FUNCTION measurement_insert_trigger()
  2. RETURNS TRIGGER AS $$
  3. BEGIN
  4. IF ( NEW.logdate >= DATE '2006-02-01' AND
  5. NEW.logdate < DATE '2006-03-01' ) THEN
  6. INSERT INTO measurement_y2006m02 VALUES (NEW.*);
  7. ELSIF ( NEW.logdate >= DATE '2006-03-01' AND
  8. NEW.logdate < DATE '2006-04-01' ) THEN
  9. ...
  10. NEW.logdate < DATE '2008-02-01' ) THEN
  11. INSERT INTO measurement_y2008m01 VALUES (NEW.*);
  12. ELSE
  13. RAISE EXCEPTION 'Date out of range. Fix the measurement_insert_trigger() function!';
  14. END IF;
  15. RETURN NULL;
  16. END;
  17. $$
  18. LANGUAGE plpgsql;

这样就OK了。

另外来实现同样插入逻辑的方式是用rule(规则)。

  1. CREATE RULE measurement_insert_y2006m02 AS
  2. ON INSERT TO measurement WHERE
  3. ( logdate >= DATE '2006-02-01' AND logdate < DATE '2006-03-01' )
  4. DO INSTEAD
  5. INSERT INTO measurement_y2006m02 VALUES (NEW.*);
  6. ...
  7. CREATE RULE measurement_insert_y2008m01 AS
  8. ON INSERT TO measurement WHERE
  9. ( logdate >= DATE '2008-01-01' AND logdate < DATE '2008-02-01' )
  10. INSERT INTO measurement_y2008m01 VALUES (NEW.*);

完结。