如何避免主表

时间:2017-07-06 16:23:11

标签: sql postgresql partitioning sql-execution-plan postgresql-9.4

我有一个表在多个表中使用inherit进行了几天的分区。

enter image description here

有一个插入触发器可以将数据插入到正确的表中,因此理论上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进行选择来过滤仍在主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上进行Seq扫描。

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 个答案:

答案 0 :(得分:1)

这是正常的,应该如此。

分区表上的每次扫描也会扫描(通常是空的)父表,因为它没有(也不能)像子表那样具有// gets all the Ids of people of category 47 var personIds = entities .Where(x => x.categoryId == 47) .Select(x => x.PersonId) .Distinct() .ToList(); // gets all rows of people of category 47 and subcategory 424 var result = entities .Where(x => personIds.Contains(x.PersonId) && x.subCategoryId == 424) .ToList(); 约束。

您可以看到此扫描不会对整个查询持续时间有任何贡献。