Postgresql日期函数扫描每个分区中的每一行,并且执行速度非常慢

时间:2018-06-01 05:46:14

标签: postgresql postgresql-9.6

我有一个很大的分区表tbl_VehicleEntry。 我创建了一个函数F_GetSysDate()(为了兼容我的函数与oracle)

CREATE TABLE tbl_vehicleentry(

vehicleentry_code numeric(12,0) NOT NULL,
shift_date timestamp without time zone NOT NULL,
shift_code numeric(1,0) NOT NULL,
booth_code numeric(2,0) NOT NULL,
.
.
N number of columns);

这样的分区......

CREATE TABLE tbl_vehicleentry_2016(

CONSTRAINT tbl_vehicleentry_2016_shift_date_check CHECK (((shift_date >= '2016-01-01'::date) AND (shift_date < '2017-01-01'::date)))

) INHERITS(tbl_vehicleentry);

ALTER TABLE tbl_vehicleentry_2016 OWNER to tms;

CREATE TABLE tbl_vehicleentry_201701(

CONSTRAINT tbl_vehicleentry_201701_shift_date_check CHECK (((shift_date >= '2017-01-01'::date) AND (shift_date < '2017-02-01'::date)))

INHERITS(tbl_vehicleentry);

ALTER TABLE tbl_vehicleentry_201701所有者tms;

CREATE TABLE tbl_vehicleentry_201702(

CONSTRAINT tbl_vehicleentry_201702_shift_date_check CHECK (((shift_date >= '2017-02-01'::date) AND (shift_date < '2017-03-01'::date)))

INHERITS(tbl_vehicleentry);

ALTER TABLE tbl_vehicleentry_201702所有者tms;

CREATE TABLE tbl_vehicleentry_201703(

CONSTRAINT tbl_vehicleentry_201703_shift_date_check CHECK (((shift_date >= '2017-03-01'::date) AND (shift_date < '2017-04-01'::date)))

INHERITS(tbl_vehicleentry);

ALTER TABLE tbl_vehicleentry_201703所有者tms;

.....等2017年以后的月份分区

-- FUNCTION: public.f_getsysdate()
-- DROP FUNCTION public.f_getsysdate();

CREATE OR REPLACE FUNCTION public.f_getsysdate(
    )
    RETURNS timestamp without time zone
    LANGUAGE 'plpgsql'

    COST 100
    STABLE SECURITY DEFINER 
AS $BODY$

DECLARE
    V_ReturnName   VARCHAR2 ;
BEGIN  
    RETURN current_timestamp::timestamp(0);
END

$BODY$;

ALTER FUNCTION public.f_getsysdate()
    OWNER TO tms;

现在,当我运行像......

这样的查询时
Explain analyze
SELECT MAX(Vehicleentry_Code) FROM tbl_VehicleEntry
WHERE Shift_Date >= f_getsysdate() - 30 

Explain analyze
SELECT MAX(Vehicleentry_Code) FROM tbl_VehicleEntry
WHERE Shift_Date >= f_getsysdate() - interval '30' day

我观察到,它正在扫描表格每个分区的每一行并使其非常慢。 以下是解释

聚合(成本= 324.08..324.09行= 1宽度= 32)    - &GT;追加(成本= 0.68..323.88行= 79宽度= 16)

    ->  Index Scan using isd_tbl_vehicleentry on tbl_vehicleentry  (cost=0.68..4.70 rows=1 width=8)
          Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))


    ->  Bitmap Heap Scan on tbl_vehicleentry_2015  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))


          ->  Bitmap Index Scan on isd_tbl_vehicleentry_2015  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_2016  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_2016  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201701  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201701  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201702  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201702  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201703  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201703  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201704  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201704  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201705  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201705  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201706  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201706  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201707  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201707  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201708  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201708  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201709  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201709  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201710  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201710  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201711  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201711  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201712  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201712  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201801  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201801  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201802  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201802  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201803  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201803  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201804  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201804  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201805  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201805  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201806  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201806  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201807  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201807  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201808  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201808  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201809  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201809  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201810  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201810  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201811  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201811  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

    ->  Bitmap Heap Scan on tbl_vehicleentry_201812  (cost=4.41..12.28 rows=3 width=16)
          Recheck Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

          ->  Bitmap Index Scan on isd_tbl_vehicleentry_201812  (cost=0.00..4.41 rows=3 width=0)
                Index Cond: (shift_date >= (f_getsysdate() - '30 days'::interval day))

**看到它扫描了postgresql表的每个分区的每一行 并使其表现得非常慢。 可能有什么不对?

问题在于功能肯定。

有没有其他方法可以让它更快? 请帮忙。**

1 个答案:

答案 0 :(得分:1)

这是因为在计划查询时不知道函数的值,因此优化器不知道是否可以排除某些分区。

首先应该查询f_getsysdate(),然后从结果中构造一个SQL语句并执行它。这样限制将是一个常量,PostgreSQL优化器可以使用它。

如果函数是IMMUTABLE,PostgreSQL可以做得更好,但根据名称,我认为这不是一个选项。