简体   繁体   English

Postgres-如何合并分区?

[英]Postgres - how to merge partitions?

I have a table that accumulates many millions of rows per day. 我有一个表,每天累积数百万行。 The most recent data is queried most frequently, as the data gets older it's queried less frequently. 最新数据的查询频率最高,因为数据越旧,查询的频率就越低。

To aid performance I've partitioned the data by month, the table(s) have been created something like this… 为了提高性能,我按月对数据进行了分区,创建了这样的表……

CREATE TABLE banana ( recTime TIMESTAMP, blah blah blah) PARTION BY RANGE (recTime);
CREATE TABLE banana_201704 PARTITION OF banana FOR VALUES FROM ('2017-04-01' ) TO (  '2017-05-01' ) ;
CREATE TABLE banana_201705 PARTITION OF banana FOR VALUES FROM ('2017-05-01' ) TO (  '2017-06-01' ) ;

I've noticed that at the start of the month I get very good performance from this table, presumably because at that time of month it has few records in it, as the month progresses (and the tables gets bigger) the performance goes down. 我注意到在月初,该表的性能非常好,大概是因为在该月的那个时候它的记录很少,随着月的进行(表变大),性能会下降。

For this reason I'm thinking that I'd get better performance if I partitioned by day, instead of by month. 因此,我认为如果按天而不是按月进行分区,将会获得更好的性能。 However, I don't want to partition the entire table by day, I'd end up with lots of little partitions to manage. 但是,我不想按天对整个表进行分区,最终我将不得不管理许多小分区。

Is it possible to somehow seamlessly merge partitions together so that after (lets say) 30 days, all the individual 'day' partitions can be merged into one big 'month' partition, without the performance overhead of simply selecting from one table, inserting into another and then deleting the original records? 是否可以通过某种方式无缝地将分区合并在一起,以便在30天之后(可以说)将所有单独的“ day”分区合并为一个大的“ month”分区,而无需简单地从一张表中进行选择,插入到其中的性能开销另一个,然后删除原始记录?

Or is there a better way to manage this? 还是有更好的方法来解决这个问题?

After the end of a month you should create a monthly table as select from the base table, drop daily partitions and attach the monthly table as a partition. 在月末之后,您应该从基本表中选择创建一个月度表,删除每日分区,并将月度表附加为一个分区。

Create daily partitions for January 2018: 创建2018年1月的每日分区:

do $$
declare d date;
begin
    for d in 
        select generate_series('2018-01-01'::date, '2018-01-31', '1d')::date
    loop
    execute format($ex$
        create table banana_%s partition of banana for values from (%L) to (%L)
        $ex$, replace(d::text, '-', ''), d, d+ 1);
    end loop;
end;
$$;

Create a single partition for the month and drop daily partitions: 为月份创建一个分区,然后删除每日分区:

create table banana_201801 as
select * from banana
where created_at between '2018-01-01' and '2018-01-31';

do $$
declare d date;
begin
    for d in 
        select generate_series('2018-01-01'::date, '2018-01-31', '1d')::date
    loop
    execute format($ex$
        drop table banana_%s
        $ex$, replace(d::text, '-', ''));
    end loop;
end;
$$;

alter table banana 
attach partition banana_201801 for values from ('2018-01-01') to ('2018-02-01');

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM