简体   繁体   中英

Add partition in existing table Greenplum

I am trying to add monthly partition on a table for an year or so. But the issue is I cannot add them in a single query. While creating the table in the past, I have added the partition for each month for couple of years.

CREATE TABLE Calls (
    callid varchar(200) NOT NULL,
    calltime timestamp NOT NULL,
    Duration varchar(50) NULL   
)
DISTRIBUTED BY (callid)
PARTITION BY RANGE(calltime) 
          (
START ('2019-04-01 00:00:00'::timestamp without time zone) END ('2022-01-01 00:00:00'::timestamp without time zone) EVERY ('1 mon'::interval) 

I read different articles and blogs on it but could not found any solution to add monthly partitions for year or so. The only possible way is to add manually one by one for each month.

alter table Calls
Add partition 
start (date '2022-01-01') inclusive 
end (date '2022-02-01')  exclusive 

--And Again for next month
 
alter table Calls
Add partition 
start (date '2022-02-01') inclusive 
end (date '2022-03-01')  exclusive 

I have around 50 60 tables and doing it manually for each table will take a lot of time and effort. I am trying to make a generic way to add partitions. Any solution?

the quickest i have always found was a dirty perl script that looped over the different ranges and just pre-writes all the SQL something like this:

$SQL = "alter table Calls Add partition start (date 'START') inclusive end (date 'END')  exclusive;";
for ($loop=<start>; $loop <= <end>; $loop+=<interval>)
{

    $SQL =~ s/START/$loop/;
    $SQL =~ s/END/END/;
    print $SQL, "\n";
}

Hope that pseudo code helps

There is no direct way for adding multiple partitions without specifying range for each partition. It will simply through error like below.

gpadmin=# alter table calls add partition START ('2022-01-01 00:00:00'::timestamp without time zone) END ('2023-01-01 00:00:00'::timestamp without time zone) EVERY ('1 mon'::interval); ERROR: cannot specify EVERY when adding RANGE partition to relation "calls" gpadmin=#

You can create new table with different partition range then replace the Calls table with new table but it a resource consuming process and requires manual intervention.

Thanks,
Anil

Managed to create a dynamic function that takes datestart text,dateend text,table_schema text,table_name text as parameter and loops over to add a partition.

CREATE OR REPLACE FUNCTION partitionfunction(datestart text,dateend text,table_schema text,table_name text)
    RETURNS void
    LANGUAGE plpgsql
    VOLATILE
AS $$
    
declare
var_Table_schema text;
var_Table_name text;
var_dateStart date;
var_dateEnd date;
var_endPartition date;
BEGIN
var_Table_schema := Table_schema;
var_Table_name := Table_name;
var_dateStart := to_date(dateStart,'YYYY-MM-DD');
var_dateEnd := to_date(dateEnd,'YYYY-MM-DD');
WHILE var_dateStart < var_dateEnd
loop
var_endPartition = var_dateStart + interval '1 MONTH'; --You can also change it for weeks or days
execute ' alter table '|| Table_schema ||'.'|| Table_name || '
add partition start('''||var_dateStart||''') end(
'''||var_endPartition||''')';
var_dateStart = var_dateStart + interval '1 MONTH'; --You can also change it for weeks or days
END loop;
end;

$$
EXECUTE ON ANY;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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