2013-11-04 92 views
3

我的分區表SELECT查詢包含所有分區表,即使檢查已就位且constraint_exclusion = on。PostgreSQL分區。 SELECT

插入觸發器工作正常,新行插入到正確的表中。但是,不管我的WHERE子句如何,SELECT都在所有表上運行。

這裏是我的配置:

constraint_exclusion = on (both in postgresql.conf and also tried with "ALTER DATABASE bigtable SET constraint_exclusion=on;") 

主表:

CREATE TABLE bigtable (
    id bigserial NOT NULL, 
    userid integer NOT NULL, 
    inserttime timestamp with time zone NOT NULL DEFAULT now() 
) 

子表1:

CREATE TABLE bigtable_2013_11 (CHECK (inserttime >= DATE '2013-11-01' AND inserttime < DATE '2013-12-01')) INHERITS (bigtable);   

子表2:

CREATE TABLE bigtable_2013_12 (CHECK (inserttime >= DATE '2013-12-01' AND inserttime < DATE '2014-01-01')) INHERITS (bigtable);  

存儲過程:

CREATE OR REPLACE FUNCTION bigtable_insert_function() 
RETURNS TRIGGER AS $$ 
BEGIN 

    IF (NEW.inserttime >= DATE '2013-11-01' AND NEW.inserttime < DATE '2013-11-01') THEN 
     INSERT INTO bigtable_2013_11 VALUES (NEW.*); 
    ELSEIF (NEW.inserttime >= DATE '2013-12-01' AND NEW.inserttime < DATE '2014-01-01') THEN 
     INSERT INTO bigtable_2013_12 VALUES (NEW.*); 
    ELSE 
     RAISE EXCEPTION 'Bigtable insert date is out of range!'; 
    END IF; 

    RETURN NULL; 
END; 
$$ 
LANGUAGE plpgsql; 

觸發:

CREATE TRIGGER bigtable_insert_trigger BEFORE INSERT ON bigtable FOR EACH ROW EXECUTE PROCEDURE bigtable_insert_function(); 

這幾乎是教科書設置。插入工作正常:

INSERT INTO bigtable (userid, inserttime) VALUES ('1', now()); 

上面的插入結果將新行正確插入到'bigtable_2013_11'中。

但是,我不能讓SELECT排除不相關的表。所有SELECT始終運行在所有表上。我希望在下面的SELECT查詢用於排除bigtable_2013_12:

SELECT * FROM bigtable WHERE inserttime >= DATE '2013-11-01'::date AND inserttime < '2013-12-01'::date; 

SELECT * FROM bigtable WHERE EXTRACT(MONTH FROM inserttime) = 11 AND EXTRACT (YEAR FROM inserttime) = 2013; 

但結果始終是這樣的:

"Result (cost=0.00..68.90 rows=17 width=20)" 
" -> Append (cost=0.00..68.90 rows=17 width=20)" 
"  -> Seq Scan on bigtable (cost=0.00..0.00 rows=1 width=20)" 
"    Filter: ((inserttime >= '2013-11-02'::date) AND (inserttime < '2013-11-30'::date))" 
"  -> Seq Scan on bigtable_2013_11 bigtable (cost=0.00..34.45 rows=8 width=20)" 
"    Filter: ((inserttime >= '2013-11-02'::date) AND (inserttime < '2013-11-30'::date))" 
"  -> Seq Scan on bigtable_2013_12 bigtable (cost=0.00..34.45 rows=8 width=20)" 
"    Filter: ((inserttime >= '2013-11-02'::date) AND (inserttime < '2013-11-30'::date))" 

爲什麼我沒有檢查踢?我沒有想法。一切似乎設置正確。我錯過了什麼嗎?任何幫助將不勝感激。

回答

2

這裏有兩件事。一個是seq掃描。另一個是union all(即附加運算符)。就我所知,後者是完全不可避免的。這就是表繼承的工作原理 - 或者最後我使用它。 *然而*,這將我們帶到前者,您可以在該日期字段上添加一個索引,以消除不必要的seq掃描和提前保釋。


或者,可能與日期/時間戳轉換有關。

+0

丹尼斯!我認爲你正在做某件事。當我將列類型更改爲DATE時,它工作正常。顯然這裏的日期/時間戳轉換確實存在問題。我會看看如何在檢查中使用時間戳而不是日期。非常感謝! – marcinx

+2

確認。在檢查和程序中使用TIMESTAMP WITH TIME ZONE而不是DATE來解決問題。再次感謝! – marcinx