2011-08-22 55 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

但是,再次,它可能會變成不成問題,這一切都取決於您的查詢和性能的期望。