Postgres:继承的性能和正确性 - 外键解决方法

时间:2011-08-22 16:18:35

标签: postgresql inheritance

我正在尝试构建我的第一个涉及继承的Postgres数据库模式。我知道PostgreSQL foreign key not existing, issue of inheritance?中讨论的外键问题。但是,这个问题的答案并没有真正为解决方案提供一个例子,所以我提出了自己的想法(灵感来自http://people.planetpostgresql.org/dfetter/index.php?/archives/51-Partitioning-Is-Such-Sweet-Sorrow.html):

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

1 个答案:

答案 0 :(得分:2)

无论如何使用继承的目的是什么?如果您只想根据行类型使用不同的列,例如在OOP中,最好使用单个表并在不适用的列中放置NULL。或者将其他列拆分为另一个表,您将其加入到原始表中。

PostgreSQL中继承的主要用途是表分区,并且有许多带有继承的警告。 PostgreSQL 9.1引入了一个“Merge Append”优化,它有所帮助,但它仍然不是最理想的。

  

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

将两个大型继承的表连接在一起听起来好像不能很好地扩展,特别是当你增加子表的数量时。 PostgreSQL不够聪明,不能遵循这里的xb和xc外键约束,它会尝试将整个表 a 连接到整个 x

但话又说回来,它可能会成为一个问题,这一切都取决于你的疑问和业绩预期。