2011-08-22 102 views
3

我正在尝试构建我的第一个涉及继承的Postgres数据库模式。我知道PostgreSQL foreign key not existing, issue of inheritance?中讨论的外键问题。然而,在这个问题的答案并没有真正举个例子的解决方案,因此我来到了我自己的(由http://people.planetpostgresql.org/dfetter/index.php?/archives/51-Partitioning-Is-Such-Sweet-Sorrow.html启发):Postgres:继承的性能和正确性 - 外键解决方法

CREATE TABLE a (
    id SERIAL PRIMARY KEY INITIALLY DEFERRED, 
    foo TEXT 
); 

CREATE TABLE b (
    PRIMARY KEY(id), 
    a_number REAL 
) inherits(a); 

CREATE TABLE c (
    PRIMARY KEY(id), 
    a_number INTEGER 
) inherits(a); 

-- SELECT * FROM ONLY a; will always return an empty record. 

CREATE TABLE x (
    a_id INTEGER NOT NULL, 
    bar TEXT 
); 

CREATE TABLE xb (
    FOREIGN KEY(a_id) REFERENCES b INITIALLY DEFERRED 
) inherits(x); 

CREATE TABLE xc (
    FOREIGN KEY(a_id) REFERENCES c INITIALLY DEFERRED 
) inherits(x); 

为了执行工作INSERT INTO x我定义以下触发:

CREATE FUNCTION marshal_x() 
    RETURNS TRIGGER 
    LANGUAGE plpgsql 
    AS $$ 
     DECLARE 
      ref_table varchar; 
     BEGIN 
      SELECT INTO ref_table p.relname FROM a, pg_class p WHERE a.id = NEW.a_id AND a.tableoid = p.oid; 

      IF ref_table = 'b' 
       THEN INSERT INTO xb (a_id, bar) VALUES (NEW.a_id, NEW.bar); 
      ELSIF ref_table = 'c' 
       THEN INSERT INTO xc (a_id, bar) VALUES (NEW.a_id, NEW.bar); 
      END IF; 
      RETURN NULL; 
     END; 
    $$; 

CREATE TRIGGER insert_x_trg 
    BEFORE INSERT ON x 
    FOR EACH ROW 
     EXECUTE PROCEDURE marshal_x(); 

编辑:有没有人看到这个定义的问题,这对我未受过训练的眼睛并不明显? 假设表c为空。会的

SELECT * FROM a JOIN x ON a.id= x.a_id; 

的性能是一样的

SELECT * FROM b JOIN x ON b.id= x.a_id; 

?提前谢谢了。

isam

回答

2

反正使用继承的目的是什么?如果你只是想要根据行类型设置不同的列,比如在OOP中,最好使用单个表并将NULL放在不适用的列中。或者将其他列分隔到另一个表中,您将其加入到原始表中。

PostgreSQL中继承的主要用途是表分区,并且有许多继承的注意事项。 PostgreSQL 9.1引入了“合并追加”优化,虽然有所帮助,但它仍然不是最理想的。

SELECT * FROM a JOIN x ON a.id = x.a_id;

连接两个大十岁上下的继承表一起听起来就像它不会规模非常好,特别是当你增加子表的数量。 PostgreSQL不够智能,不能遵循这里的xb和xc外键约束,它会尝试加入整个表a到整个x

但是,再次,它可能会变成不成问题,这一切都取决于您的查询和性能的期望。