2015-11-05 63 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支持基于列表或基于范围的分区。这就是为什么你必须提供一个范围,但不是一个功能。 –