【问题标题】:Postgres: Performance and correctness of inheritance-foreign-key workaroundPostgres:继承-外键解决方法的性能和正确性
【发布时间】:2011-08-22 16:18:34
【问题描述】:

我正在尝试构建我的第一个涉及继承的 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;

?非常感谢。

伊萨姆

【问题讨论】:

    标签: postgresql inheritance


    【解决方案1】:

    到底使用继承的目的是什么?如果您只想根据行类型来使用不同的列,例如在 OOP 中,您最好使用单个表并将 NULL 放在不适用的列中。或者将其他列拆分到另一个表中,然后将其连接到原始表中。

    PostgreSQL 中继承的主要用途是表分区,继承有许多注意事项。 PostgreSQL 9.1 引入了“Merge Append”优化,这在一定程度上有所帮助,但仍然不是最理想的。

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

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

    但话又说回来,这可能不是问题,这完全取决于您的查询和性能预期。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-30
      • 2017-04-14
      • 1970-01-01
      • 2011-11-07
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多