2015-11-05 37 views
0

我使用PostgreSQL創建分區表。使用動態參數檢查約束條件

CREATE TABLE tt_parent 
(
    id integer, 
    log_time timestamp with time zone, 
    server_id integer, 
    name text, 
    CONSTRAINT tt_parent_pkey PRIMARY KEY (id) 
) 

CREATE TABLE tt_1_2015_week42 (
CHECK (server_id = 1 AND log_time >= (to_timestamp('2015-42', 'IYYY-IW')) AND log_time <= (to_timestamp('2015-42', 'IYYY-IW') + '6 days'::interval) 
) INHERITS (tt_parent); 

CREATE TABLE tt_1_2015_week43 (
CHECK (server_id = 1 AND log_time >= (to_timestamp('2015-43', 'IYYY-IW')) AND log_time <= (to_timestamp('2015-43', 'IYYY-IW') + '6 days'::interval) 
) INHERITS (tt_parent); 

CREATE TABLE tt_1_2015_week44 (
CHECK (server_id = 1 AND log_time >= (to_timestamp('2015-44', 'IYYY-IW')) AND log_time <= (to_timestamp('2015-44', 'IYYY-IW') + '6 days'::interval) 
) INHERITS (tt_parent); 

創建上述子表時,當我在下面查詢時觸發,然後它掃描所有的子表。

EXPLAIN SELECT * FROM tt_parent 
WHERE server_id = 1 
AND (log_time >= '2015-10-12 00:00:00'::TIMESTAMP WITH TIME ZONE) 
AND (log_time <= '2015-10-15 00:00:00'::TIMESTAMP WITH TIME ZONE); 

從上面的查詢,log_time在where子句是42周所以查詢應該只掃描「tt_1_2015_week42」子表。 爲什麼上面的查詢掃描所有3個子表?

使用動態值檢查約束不起作用?我們不能在Check約束中使用「to_timestamp」函數嗎? 如何修改上面的子表檢查約束,以便查詢只掃描第42周的表。

回答

0

1)您的檢查條件缺少兩個相鄰分區之間的時間段。例如,間隙:

from: to_timestamp('2015-42', 'IYYY-IW') + '6 days'::interval --2015-10-18 00:00:00 
to: to_timestamp('2015-43', 'IYYY-IW'))      --2015-10-19 00:00:00 

我會寫:

CHECK (
    server_id = 1 AND 
    log_time >= '2015-10-12'::timestamptz AND 
    log_time < '2015-10-12'::timestamptz + interval '1 week' --'<' sign, not '<=' to avoid overlapping 
) 

2)爲了得到你想要的東西,你需要一個constraint_exclusion設置選項partition(這應該是默認值)。

+0

從這個選項我也嘗試過,但後來還查詢掃描所有3個表。根據我的理解,它應該只掃描「tt_1_2015_week42」表,因爲where子句中的日期是在第42周。 – Neel

+0

其實是的。你不能使用'to_timestamp',因爲這是一個函數。 Postgresql支持基於列表或基於範圍的分區。這就是爲什麼你必須提供一個範圍,但不是一個功能。 –