Postgres-如何合并分区?

时间:2018-07-18 09:45:33

标签: postgresql database-partitioning

我有一个表,每天累积数百万行。最新数据的查询频率最高,而随着数据的老化,查询频率也会降低。

为了提高性能,我已经按月对数据进行了分区,创建的表是这样的……

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' ) ;

我注意到在月初我从该表中获得了很好的性能,大概是因为在该月的那个时候它的记录很少,随着月的进行(表变得更大),性能下来。

基于这个原因,我认为如果按天而不是按月进行分区,则性能会更好。但是,我不想按天对整个表进行分区,最终会产生很多小的分区要管理。

是否可以以某种方式无缝地将分区合并在一起,以便(假设)30天后,所有单独的“ day”分区都可以合并到一个大的“ month”分区中,而无需从一个表中简单选择性能开销,插入另一个,然后删除原始记录?

还是有更好的方法来管理此问题?

1 个答案:

答案 0 :(得分:0)

一个月后,您应该从基本表中选择创建一个月度表,删除每日分区,并将月度表附加为分区。

创建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 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');