Postgresql 在postgres 11中,分区表的规划时间需要更多的时间

Postgresql 在postgres 11中,分区表的规划时间需要更多的时间,postgresql,query-optimization,postgresql-11,Postgresql,Query Optimization,Postgresql 11,我有不到200个分区(每日分区),每个分区有5万条以上的记录 当我用直接分区传递一天的数据时,我看到估计的计划为0.01ms,但使用父表时为190ms(太多)。唯一观察到的差异是在计划中追加 我们可以在postgres 11中消除追加或减少修剪时间吗 查询: explain(分析、详细、成本、缓冲、计时、摘要)从测试中选择1,其中date1>'2021-01-27 13:41:26'和date1索引仅在测试上使用test_20210127_pkey进行扫描_20210127(成本=0.12..4

我有不到200个分区(每日分区),每个分区有5万条以上的记录

当我用直接分区传递一天的数据时,我看到估计的计划为0.01ms,但使用父表时为190ms(太多)。唯一观察到的差异是在计划中追加

我们可以在postgres 11中消除追加或减少修剪时间吗

查询:

explain(分析、详细、成本、缓冲、计时、摘要)从测试中选择1,其中date1>'2021-01-27 13:41:26'和date1索引仅在测试上使用test_20210127_pkey进行扫描_20210127(成本=0.12..4.17行=1宽度=4)(实际时间=0.017..0.017行=0循环=1)
产出:1
索引条件:((test_20210127.date1>'2021-01-27 13:41:26':无时区的时间戳)和(test_20210127.date1<'2021-01-27 21:41:26':无时区的时间戳)和(test_20210127.own=123)和(test_20210127.mob=123454234))
堆获取:0
缓冲区:共享命中=1
计划时间:190.440毫秒
执行时间:0.093毫秒
------------剪台结构----


您可以升级到更高版本的PostgreSQL,因为v12中的性能有所提高

但如果查询执行时间短,计划时间将始终占主导地位。您可以测试一个准备好的语句,但我怀疑运行时分区修剪会快得多


从本质上讲,查询性能越差,这是您为放弃旧数据的简单方法所付出的预期代价。

我为您修复了格式设置。对于将来的问题,请确保“按原样”粘贴执行计划,不要弄乱换行符,并确保保留计划的缩进。否则它是无法实现的为什么你每天只使用500万条记录的分区?有了这些数据量,我将使用最少一个月的分区。这将为您提供200天的7个分区,可能会缩短规划时间。只有我会保留6个月的数据,这样我们才能正确删除旧分区?考虑到时间戳的分辨率,在主键中包含时间戳似乎很奇怪。我知道这是因为Postgres没有全局索引,但仍然。。。如果你移除主键,计划时间会改变吗?没有PK,同样的问题@a_horse_,有_no_name谢谢你的回答@laurez Albe。但现在不可能迁移到12。我也试过用准备好的语句,但没有用。至少我想降低到40毫秒以下。参数设置更改方面有任何建议。没有;你必须接受它。唯一的补救办法是直接从分区中进行选择-但是如果您首先必须确定它是哪个分区,那么这可能需要至少与分区修剪一样长的时间。如果它超过1个(如果我们过滤超过1个日期分区),那么为什么要在一个分区过滤器中添加append(在计划中)append是有意义的,但这并不有害。如您所见,它需要0.001毫秒。
CREATE TABLE public.test
(
    own integer NOT NULL,
    mob bigint NOT NULL,  
    date1 timestamp without time zone NOT NULL,    
    ver integer NOT NULL,
    c5
    ...
    c100
    CONSTRAINT test_pkey PRIMARY KEY (date1, own, mob, ver)
        USING INDEX TABLESPACE tb_1
) PARTITION BY RANGE (date1) 
WITH (
    OIDS = FALSE
)
TABLESPACE tb_1;
 

-- Partitions SQL

CREATE TABLE public.test_20211003 PARTITION OF public.test
    FOR VALUES FROM ('2020-10-03 00:00:00') TO ('2020-10-04 00:00:00');

CREATE TABLE public.test_201004 PARTITION OF public.test
    FOR VALUES FROM ('2020-10-04 00:00:00') TO ('2020-10-05 00:00:00');

  ........6 months partitions