2010-06-19 140 views
3

我建立了一套%的文檔分區表的http://www.postgresql.org/docs/8.1/interactive/ddl-partitioning.html如何在分區表中插入和選擇數據?

CREATE TABLE t (year, a); 
CREATE TABLE t_1980 (CHECK (year = 1980)) INHERITS (t); 
CREATE TABLE t_1981 (CHECK (year = 1981)) INHERITS (t); 
CREATE RULE t_ins_1980 AS ON INSERT TO t WHERE (year = 1980) 
    DO INSTEAD INSERT INTO t_1980 VALUES (NEW.year, NEW.a); 
CREATE RULE t_ins_1981 AS ON INSERT TO t WHERE (year = 1981) 
    DO INSTEAD INSERT INTO t_1981 VALUES (NEW.year, NEW.a); 

從我的理解,如果我INSERT INTO T(一年一)VALUES(1980,5),它會去t_1980,和如果我插入t(year,a)VALUES(1981,3),它將轉到t_1981。但是,我的理解似乎是不正確的。首先,我無法理解文檔中的以下內容

「目前還沒有簡單的方法來指定行不能插入主表中。主表上的CHECK(false)約束將被所有的子表,所以不能用於此目的,一種可能是在主表上設置一個總是引發錯誤的ON INSERT觸發器(或者,這樣的觸發器可以用來將數據重定向到合適的子表,而不是使用上面建議的一組規則。)「

以上是否意味着儘管設置了CHECK約束和RULE,我還必須在主表上創建TRIGGER,以便INSERT去正確的表?如果是這樣的話,db支持分區的要點是什麼?我可以自己設置單獨的表格嗎?我在主表中插入了一堆值,這些行仍在主表中,而不在繼承的表中。

第二個問題。當檢索行時,是從主表中選擇,還是必須根據需要從各個表中進行選擇?以下工作如何?

SELECT year, a FROM t WHERE year IN (1980, 1981); 

更新:好像我已經找到了答案,以我自己的問題

「請注意,COPY命令將忽略規則,如果你正在使用COPY中插入數據,你必須複製數據插入到正確的子表中而不是放入父項中COPY確實觸發了觸發器,因此如果使用觸發器方法創建分區表,則可以正常使用它。

我的確在使用COPY FROM加載數據,所以RULEs被忽略。將嘗試使用TRIGGER。

回答

3

肯定嘗試觸發器。

如果你認爲你想實現一個規則,不要(唯一想到的例外是可更新的視圖)。請參閱此great article by depesz以瞭解更多解釋。

實際上,Postgres只支持事物讀取的分區。您將自己設置插入分區的方法 - 大多數情況下爲TRIGGERing。根據需要和應用程序,教您的應用程序直接插入分區有時會更快。

從分區表中選擇時,只要您的CHECK約束條件已正確設置(您的示例中爲正確設置)並且constraint_exclusion參數設置爲正確,那麼只需在主表上選擇... WHERE ...即可。

對於8.4:

SET constraint_exclusion = partition; 

對於< 8。4:

SET constraint_exclusion = on; 

所有這一切被說,我其實很喜歡Postgres的做法,並經常使用它。

1

上面是否意味着,儘管 建立CHECK約束和 規則,我也有在主表,以便 嵌件到正確的表上創建觸發器 ?

是的。閱讀point 5 (section 5.9.2)

如果是這樣的話,這將是 數據庫支持 分割點?我可以自己設置 單獨的表格嗎?

基本上:子表中的INSERTS必須顯式地完成(或者創建TRIGGERS,或者通過在查詢中指定正確的子表)。但分區 對於SELECTS是透明的,並且(考慮到該模式的存儲和索引優勢)就是重點。 (此外,因爲分區表是繼承的,所以該模式從父代繼承,因此一致性 被強制執行)。

1

觸發器優於規則。 今天我玩了物化視圖表的分區,並遇到觸發器解決方案的問題。 爲什麼? 我使用RETURNING和當前的解決方案返回NULL :) 但是這裏的解決方案適用於我 - 糾正我,如果我錯了。 1.我有3個插入了一些數據的表格,有一個包含 數據的視圖(讓我們稱之爲viewfoo)。 2.插入到最後一個表中具有觸發器,該觸發器通過INSERT INTO插入物化視圖表 matviewtable SELECT * FROM viewfoo WHERE recno = NEW.recno; 這工作正常,我使用RETURNING recno; (recno是SERIAL類型 - 序列)。

物化視圖(表格)需要分區,因爲它是巨大的,根據我的測試, 在這種情況下SELECT至少要快10倍。 分區問題: *當前觸發解決方案RETURN NULL - 所以我不能使用RETURNING recno。 (當前觸發解決方案=在depesz頁面解釋的觸發器)。

解決方案: 我已經改變了我的第三臺的觸發不插入到物化視圖表(該表是分區表的母公司),但創造了新的觸發器,它直接插入 分區表從第3表和觸發器回新。 物化視圖表被自動更新並且RETURNING recno正常工作。 如果這有助於任何人,我會很高興。

相關問題