0

我有一个表使用多个表中的继承分区数天。如何避免主表中的扫描

enter image description here

有一个INSERT触发器将数据插入到适当的表,所以理论上AVL表不应该有任何的数据

CREATE OR REPLACE FUNCTION avl_db.avl_insert_trigger() 
    RETURNS trigger AS 
$BODY$ 
BEGIN 
    IF (NEW.event_time >= '2017-06-01 00:00:00' AND NEW.event_time < '2017-06-02 00:00:00') THEN 
     INSERT INTO avl_db.avl_20170601 VALUES (NEW.*); 
    ELSEIF (NEW.event_time >= '2017-06-02 00:00:00' AND NEW.event_time < '2017-06-03 00:00:00') THEN 
     INSERT INTO avl_db.avl_20170602 VALUES (NEW.*); 
    ELSEIF (NEW.event_time >= '2017-06-03 00:00:00' AND NEW.event_time < '2017-06-04 00:00:00') THEN 
     INSERT INTO avl_db.avl_20170603 VALUES (NEW.*); 
    ELSEIF (NEW.event_time >= '2017-06-04 00:00:00' AND NEW.event_time < '2017-06-05 00:00:00') THEN 
     INSERT INTO avl_db.avl_20170604 VALUES (NEW.*); 
    ELSEIF (NEW.event_time >= '2017-06-05 00:00:00' AND NEW.event_time < '2017-06-06 00:00:00') THEN 
     INSERT INTO avl_db.avl_20170605 VALUES (NEW.*); 
.... 
    ELSE 
     RAISE EXCEPTION 'Date out of range.'; 
    END IF; 

    RETURN NULL; 

每个表都有一个检查约束,因此只有指数检查表与正确的日期

CONSTRAINT avl_20170605_event_time_check 
CHECK (event_time >= '2017-06-05 00:00:00'::timestamp without time zone 
    AND event_time < '2017-06-06 00:00:00'::timestamp without time zone) 

CREATE INDEX avl_20170605__event_time_idx 
    ON avl_db.avl_20170605 
    USING btree 
    (event_time); 

的事情是什么时候使用event_time过滤仍然d选择o对主表avl进行一些操作。

explain analyze 
    SELECT * 
    FROM avl_db.avl 
    WHERE event_time between '2017-06-05 09:40:44'::timestamp without time zone - '6 minute'::interval 
         AND '2017-06-05 09:40:44'::timestamp without time zone - '1 minute'::interval 

你可以看到从avl_20170605__event_time_idx使用索引,而忽略了表的其余部分,也尝试着做一个序列扫描上avl

Append (cost=0.00..720.98 rows=7724 width=16) (actual time=0.044..5.523 rows=7851 loops=1) 
    -> Seq Scan on avl (cost=0.00..0.00 rows=1 width=16) (actual time=0.001..0.001 rows=0 loops=1) 
     Filter: ((event_time >= '2017-06-05 09:34:44'::timestamp without time zone) AND (event_time <= '2017-06-05 09:39:44'::timestamp without time zone)) 
    -> Index Scan using avl_20170605__event_time_idx on avl_20170605 (cost=0.42..720.98 rows=7723 width=16) (actual time=0.042..5.110 rows=7851 loops=1) 
     Index Cond: ((event_time >= '2017-06-05 09:34:44'::timestamp without time zone) AND (event_time <= '2017-06-05 09:39:44'::timestamp without time zone)) 
Planning time: 3.050 ms 
Execution time: 5.737 ms 

我不知道是否有一种方法优化停止尝试扫描并追加表avl

+1

对于只有一行,执行“Seq扫描”是唯一有效的方法。 –

+0

另外,向我们展示您的创建触发器 - 是之前还是之后? –

+0

@a_horse_with_no_name我看到'row = 1'。但是这没有任何意义,那里不应该有任何行。有什么方法可以看到哪一排?而我的问题更像是当我添加'CHECK'约束时,优化器只检查一个表。所以也许我可以设置这么忽略主表。 –

回答

1

这是正常的,因为它应该是。

对分区表的每次扫描也会扫描(通常是空的)父表,因为它没有(也不能)像子表一样具有约束条件。

您可以看到,此扫描不会为整个查询时间带来任何时间。