2024년 7월 25일 목요일

Greenplum 7 파티션

Greenplum 7에서 파티션 관리

스크립트: https://github.com/gpdbkr/Greenplum7/blob/main/Greenplum7_partition.sql


--##### 1.1 Greenplum 6 OR Greenplum 7 파티션 테이블 생성

DROP TABLE IF EXISTS public.order_log;

CREATE TABLE public.order_log

(

order_no int,

cust_no int,

prod_nm TEXT,

order_date date

)

WITH (appendonly=TRUE, compresstype=zstd, compresslevel=7)

DISTRIBUTED BY (order_no)

PARTITION BY RANGE (order_date)

(

PARTITION p2001 start('2001-01-01'::date) END ('2002-01-01'::date),

PARTITION p2002 start('2002-01-01'::date) END ('2003-01-01'::date),

PARTITION p2003 start('2003-01-01'::date) END ('2004-01-01'::date),

PARTITION p2004 start('2004-01-01'::date) END ('2005-01-01'::date),

PARTITION p2005 start('2005-01-01'::date) END ('2006-01-01'::date)

)

;


SELECT t1.nspname, t2.relname

, pg_get_expr(relpartbound, t2.oid)

, relispartition

, t2.reloptions

FROM pg_namespace t1

JOIN pg_class t2

ON t1.oid = t2.relnamespace

WHERE 1=1

AND t2.relispartition = TRUE

AND t1.nspname = 'public'

AND t2.relname LIKE 'order_log%' ;

nspname|relname |pg_get_expr |relispartition|reloptions |

-------+---------------------+------------------------------------------------+--------------+-----------------------------------------------------------------+

public |order_log_1_prt_p2001|FOR VALUES FROM ('2001-01-01') TO ('2002-01-01')|true |{compresstype=zstd,compresslevel=7,blocksize=32768,checksum=true}|

public |order_log_1_prt_p2002|FOR VALUES FROM ('2002-01-01') TO ('2003-01-01')|true |{compresstype=zstd,compresslevel=7,blocksize=32768,checksum=true}|

public |order_log_1_prt_p2003|FOR VALUES FROM ('2003-01-01') TO ('2004-01-01')|true |{compresstype=zstd,compresslevel=7,blocksize=32768,checksum=true}|

public |order_log_1_prt_p2004|FOR VALUES FROM ('2004-01-01') TO ('2005-01-01')|true |{compresstype=zstd,compresslevel=7,blocksize=32768,checksum=true}|

public |order_log_1_prt_p2005|FOR VALUES FROM ('2005-01-01') TO ('2006-01-01')|true |{compresstype=zstd,compresslevel=7,blocksize=32768,checksum=true}|


--##### 1.2 Greenplum 7 파티션 테이블 생성 (GP7만 지원)

--테이블 생성시 테이블 압축 옵션 적용할 경우, 개별적 파티션을 만들때 압축 옵션이 자동 적용 됨.

--단,개별적 파티션에 저장 옵션을 적용할 경우,파티션 저장 옵션이 우선 함.

--Greenplum 6의 파티션 생성 명명법에 따라 파티션 명을 정하는 것이 좋음. _1_prt_일 경우 파티션 인지가 빠름.

DROP TABLE IF EXISTS public.order_log;

CREATE TABLE public.order_log

(

order_no int,

cust_no int,

prod_nm TEXT,

order_date date

)

WITH (appendonly=TRUE, compresstype=zstd, compresslevel=7)

DISTRIBUTED BY (order_no)

PARTITION BY RANGE (order_date)

;


SELECT t1.nspname, t2.relname

, pg_get_expr(relpartbound, t2.oid)

, relispartition

, t2.reloptions

FROM pg_namespace t1

JOIN pg_class t2

ON t1.oid = t2.relnamespace

WHERE 1=1

AND t2.relispartition = TRUE

AND t1.nspname = 'public'

AND t2.relname LIKE 'order_log%' ;


--파티션이 생성되어 있지 않음.

nspname|relname|pg_get_expr|relispartition|reloptions|

-------+-------+-----------+--------------+----------+



-- Greenplum 7에서만 지원되는 형태, 파티션 테이블임을 선언만 하고, 개별적으로 파티션 만듬. 

DROP TABLE IF EXISTS public.order_log;

CREATE TABLE public.order_log

(

order_no int,

cust_no int,

prod_nm TEXT,

order_date date

)

WITH (appendonly=TRUE, compresstype=zstd, compresslevel=7)

DISTRIBUTED BY (order_no)

PARTITION BY RANGE (order_date)

;


-- 파티션 명을 [테이블명][_1_prt_][파티션명]으로 할 경우, 파티션 테이블 한번에 생성할 때의 파티션명과 동일

CREATE TABLE public.order_log_1_prt_p2001 PARTITION OF public.order_log FOR VALUES FROM ('2001-01-01'::date) TO ('2002-01-01'::date) WITH (appendonly=FALSE);

CREATE TABLE public.order_log_1_prt_p2002 PARTITION OF public.order_log FOR VALUES FROM ('2002-01-01'::date) TO ('2003-01-01'::date) WITH (appendonly=TRUE, compresstype=zstd, compresslevel=1);

CREATE TABLE public.order_log_1_prt_p2003 PARTITION OF public.order_log FOR VALUES FROM ('2003-01-01'::date) TO ('2004-01-01'::date) WITH (appendonly=TRUE, compresstype=zstd, compresslevel=2);

CREATE TABLE public.order_log_1_prt_p2004 PARTITION OF public.order_log FOR VALUES FROM ('2004-01-01'::date) TO ('2005-01-01'::date) WITH (appendonly=TRUE, compresstype=zstd, compresslevel=3);

CREATE TABLE public.order_log_1_prt_p2005 PARTITION OF public.order_log FOR VALUES FROM ('2005-01-01'::date) TO ('2006-01-01'::date);



SELECT t1.nspname, t2.relname

, pg_get_expr(relpartbound, t2.oid)

, relispartition

, t2.reloptions

FROM pg_namespace t1

JOIN pg_class t2

ON t1.oid = t2.relnamespace

WHERE 1=1

AND t2.relispartition = TRUE

AND t1.nspname = 'public'

AND t2.relname LIKE 'order_log%' ;

--

nspname|relname |pg_get_expr |relispartition|reloptions |

-------+---------------------+------------------------------------------------+--------------+-----------------------------------------------------------------+

public |order_log_1_prt_p2001|FOR VALUES FROM ('2001-01-01') TO ('2002-01-01')|true |NULL |

public |order_log_1_prt_p2002|FOR VALUES FROM ('2002-01-01') TO ('2003-01-01')|true |{compresstype=zstd,compresslevel=1,blocksize=32768,checksum=true}|

public |order_log_1_prt_p2003|FOR VALUES FROM ('2003-01-01') TO ('2004-01-01')|true |{compresstype=zstd,compresslevel=2,blocksize=32768,checksum=true}|

public |order_log_1_prt_p2004|FOR VALUES FROM ('2004-01-01') TO ('2005-01-01')|true |{compresstype=zstd,compresslevel=3,blocksize=32768,checksum=true}|

public |order_log_1_prt_p2005|FOR VALUES FROM ('2005-01-01') TO ('2006-01-01')|true |{compresstype=zstd,compresslevel=7,blocksize=32768,checksum=true}|



--##### 2.1 파티션 테이블의 Root 파티션에 데이터 적재

--Root 파티션에 데이터 적재

INSERT INTO public.order_log

SELECT i order_no

, i%100 cust_no

, 'prod_'||trim(to_char(i%50, '00000')) prod_nm

, '2001-01-01'::date + i order_date

FROM generate_series(1, 1825) i

;


SELECT count(*) FROM public.order_log ;

--1,825 rows


--##### 2.2 특정 파티션에 DML 수행

--해당 파티션에 데이터 적재

SELECT count(*) FROM public.order_log_1_prt_p2001;

--364


TRUNCATE TABLE public.order_log;


--###################### 특정 파티션에 INSERT ######################

INSERT INTO public.order_log_1_prt_p2001

SELECT i order_no

, i%100 cust_no

, 'prod_'||trim(to_char(i%50, '00000')) prod_nm

, '2001-01-01'::date + i order_date

FROM generate_series(1, 364) i

;

--364 rows


--###################### 특정 파티션에 UPDATE ######################

UPDATE public.order_log_1_prt_p2001

SET prod_nm = 'prod_name'

WHERE order_date >= '2001-01-01'

AND order_date <= '2001-12-31'

;

--364 rows


--###################### 특정 파티션에 DELETE ######################

DELETE FROM public.order_log_1_prt_p2001

WHERE order_date >= '2001-01-01'

AND order_date <= '2001-12-31'

;

--364 rows


--##### 3. 파티션 관리

--파티션 생성, 추가, Detach & Attach, 파티션명 변경, 파티션 삭제, Default 파티션 추가

--3.1 Greenplum 7 파티션 추가

DROP TABLE IF EXISTS public.order_log;

CREATE TABLE public.order_log

(

order_no int,

cust_no int,

prod_nm TEXT,

order_date date

)

WITH (appendonly=TRUE, compresstype=zstd, compresslevel=7)

DISTRIBUTED BY (order_no)

PARTITION BY RANGE (order_date)

(

PARTITION p2001 start('2001-01-01'::date) END ('2002-01-01'::date),

PARTITION p2002 start('2002-01-01'::date) END ('2003-01-01'::date),

PARTITION p2003 start('2003-01-01'::date) END ('2004-01-01'::date)

)

;


--### Greenplum 7에서는 2가지 커멘드로 파티션을 추가 할 수 있음.

--1) Add Partition 방법

ALTER TABLE public.order_log ADD PARTITION p2004 start('2004-01-01'::date) END ('2005-01-01'::date);



--2) 테이블을 생성하면서 Root 파티션의 일부로 인식하는 방식

--단이방식으로는 테이블명을 "_1_prt_" 까지 넣으면, 테이블 생성시의 파티션명 룰 또는 Add Partitoin과 동일한 네이밍룰을 따라 갈 수 있음.

CREATE TABLE public.order_log_1_prt_p2005 PARTITION OF public.order_log FOR VALUES FROM ('2005-01-01'::date) TO ('2006-01-01'::date);


--3) Default 파티션 추가

ALTER TABLE public.order_log ADD DEFAULT PARTITION pother;



SELECT schemaname, tablename, partitiontablename, partitiontype, partitionboundary

FROM gp_toolkit.gp_partitions

WHERE schemaname = 'public'

AND tablename = 'order_log'

;


--

schemaname|tablename|partitiontablename |partitiontype|partitionboundary |

----------+---------+----------------------+-------------+------------------------------------------------+

public |order_log|order_log_1_prt_p2001 |range |FOR VALUES FROM ('2001-01-01') TO ('2002-01-01')|

public |order_log|order_log_1_prt_p2002 |range |FOR VALUES FROM ('2002-01-01') TO ('2003-01-01')|

public |order_log|order_log_1_prt_p2003 |range |FOR VALUES FROM ('2003-01-01') TO ('2004-01-01')|

public |order_log|order_log_1_prt_p2004 |range |FOR VALUES FROM ('2004-01-01') TO ('2005-01-01')|

public |order_log|order_log_1_prt_p2005 |range |FOR VALUES FROM ('2005-01-01') TO ('2006-01-01')|

public |order_log|order_log_1_prt_pother|range |DEFAULT |



--##### 3.2 파티션 Detach & Attach, 파티션명 변경, 파티션 삭제, Default 파티션 추가

--특정 파티션을 일반 테이블로 생성함.

DROP TABLE IF EXISTS public.order_log;

CREATE TABLE public.order_log

(

order_no int,

cust_no int,

prod_nm TEXT,

order_date date

)

WITH (appendonly=TRUE, compresstype=zstd, compresslevel=7)

DISTRIBUTED BY (order_no)

PARTITION BY RANGE (order_date)

(

PARTITION p2001 start('2001-01-01'::date) END ('2002-01-01'::date),

PARTITION p2002 start('2002-01-01'::date) END ('2003-01-01'::date),

PARTITION p2003 start('2003-01-01'::date) END ('2004-01-01'::date),

PARTITION p2004 start('2004-01-01'::date) END ('2005-01-01'::date),

PARTITION p2005 start('2005-01-01'::date) END ('2006-01-01'::date)

)

;



SELECT t1.nspname, relname, relkind, relhassubclass, relispartition

FROM pg_namespace t1

JOIN pg_class t2

ON t1.oid = t2.relnamespace

WHERE 1=1

AND t1.nspname = 'public'

AND t2.relname LIKE 'order_log%';


--output

nspname|relname |relkind|relhassubclass|relispartition|

-------+---------------------+-------+--------------+--------------+

public |order_log |p |true |false | ==> Root 파티

public |order_log_1_prt_p2001|r |false |true | ==> 아래로 파티

public |order_log_1_prt_p2002|r |false |true |

public |order_log_1_prt_p2003|r |false |true |

public |order_log_1_prt_p2004|r |false |true |

public |order_log_1_prt_p2005|r |false |true | ==>DETACH 할 예정



--파티션 Detach, order_log_1_prt_p2005 파티션이 파티션 분리 => 즉 특정 파티션을 테이블로 치환

ALTER TABLE public.order_log DETACH PARTITION order_log_1_prt_p2005;



SELECT schemaname, tablename, partitiontablename, partitiontype, partitionboundary

FROM gp_toolkit.gp_partitions

WHERE schemaname = 'public'

AND tablename = 'order_log'

;

-- output

schemaname|tablename|partitiontablename |partitiontype|partitionboundary |

----------+---------+---------------------+-------------+------------------------------------------------+

public |order_log|order_log_1_prt_p2001|range |FOR VALUES FROM ('2001-01-01') TO ('2002-01-01')|

public |order_log|order_log_1_prt_p2002|range |FOR VALUES FROM ('2002-01-01') TO ('2003-01-01')|

public |order_log|order_log_1_prt_p2003|range |FOR VALUES FROM ('2003-01-01') TO ('2004-01-01')|

public |order_log|order_log_1_prt_p2004|range |FOR VALUES FROM ('2004-01-01') TO ('2005-01-01')|


-- output

SELECT t1.nspname, relname, relkind, relhassubclass, relispartition

FROM pg_namespace t1

JOIN pg_class t2

ON t1.oid = t2.relnamespace

WHERE 1=1

AND t1.nspname = 'public'

AND t2.relname LIKE 'order_log%';

nspname|relname |relkind|relhassubclass|relispartition|

-------+---------------------+-------+--------------+--------------+

public |order_log |p |true |false |

public |order_log_1_prt_p2001|r |false |true |

public |order_log_1_prt_p2002|r |false |true |

public |order_log_1_prt_p2003|r |false |true |

public |order_log_1_prt_p2004|r |false |true |

public |order_log_1_prt_p2005|r |false |false | ==> 기존 파티션이 일반 테이블로 분리. relispartition 필드가 FALSE 변경



--테이블과 파티션 이름이 혼동될 수 있어서 detach된 테이블명 이름 변경하는 것이 좋을 것 같음.

ALTER TABLE public.order_log_1_prt_p2005 RENAME TO order_log_p2005;


SELECT t1.nspname, relname, relkind, relhassubclass, relispartition

FROM pg_namespace t1

JOIN pg_class t2

ON t1.oid = t2.relnamespace

WHERE 1=1

AND t1.nspname = 'public'

AND t2.relname LIKE 'order_log%';


nspname|relname |relkind|relhassubclass|relispartition|

-------+---------------------+-------+--------------+--------------+

public |order_log |p |true |false |

public |order_log_1_prt_p2001|r |false |true |

public |order_log_1_prt_p2002|r |false |true |

public |order_log_1_prt_p2003|r |false |true |

public |order_log_1_prt_p2004|r |false |true |

public |order_log_p2005 |r |false |false |



--기존 테이블 Attach

ALTER TABLE public.order_log ATTACH PARTITION order_log_p2005

FOR VALUES FROM ('2005-01-01'::date) TO ('2006-01-01'::date) --파티션 구간

;


--

SELECT schemaname, tablename, partitiontablename, partitiontype, partitionboundary

FROM gp_toolkit.gp_partitions

WHERE schemaname = 'public'

AND tablename = 'order_log'

;

--output

schemaname|tablename|partitiontablename |partitiontype|partitionboundary |

----------+---------+---------------------+-------------+------------------------------------------------+

public |order_log|order_log_1_prt_p2001|range |FOR VALUES FROM ('2001-01-01') TO ('2002-01-01')|

public |order_log|order_log_1_prt_p2002|range |FOR VALUES FROM ('2002-01-01') TO ('2003-01-01')|

public |order_log|order_log_1_prt_p2003|range |FOR VALUES FROM ('2003-01-01') TO ('2004-01-01')|

public |order_log|order_log_1_prt_p2004|range |FOR VALUES FROM ('2004-01-01') TO ('2005-01-01')|

public |order_log|order_log_p2005 |range |FOR VALUES FROM ('2005-01-01') TO ('2006-01-01')| --> Attach



--Greenplum 7에서의 파티션명 변경.

ALTER TABLE public.order_log_p2005 RENAME TO order_log_1_prt_p2005;


SELECT schemaname, tablename, partitiontablename, partitiontype, partitionboundary

FROM gp_toolkit.gp_partitions

WHERE schemaname = 'public'

AND tablename = 'order_log'

;


schemaname|tablename|partitiontablename |partitiontype|partitionboundary |

----------+---------+---------------------+-------------+------------------------------------------------+

public |order_log|order_log_1_prt_p2001|range |FOR VALUES FROM ('2001-01-01') TO ('2002-01-01')|

public |order_log|order_log_1_prt_p2002|range |FOR VALUES FROM ('2002-01-01') TO ('2003-01-01')|

public |order_log|order_log_1_prt_p2003|range |FOR VALUES FROM ('2003-01-01') TO ('2004-01-01')|

public |order_log|order_log_1_prt_p2004|range |FOR VALUES FROM ('2004-01-01') TO ('2005-01-01')|

public |order_log|order_log_1_prt_p2005|range |FOR VALUES FROM ('2005-01-01') TO ('2006-01-01')| --> 파티션명 변경


--Greenplum 7에서 Greenplum 6의 파티션명 변경 명령어는 수행되지 않음. => 에러 발

ALTER TABLE public.order_log RENAME PARTITION p2005 TO _1_prt_p2005;


--##### 3.3 Greenplum 7 파티션 Drop

DROP TABLE IF EXISTS public.order_log;

CREATE TABLE public.order_log

(

order_no int,

cust_no int,

prod_nm TEXT,

order_date date

)

WITH (appendonly=TRUE, compresstype=zstd, compresslevel=7)

DISTRIBUTED BY (order_no)

PARTITION BY RANGE (order_date)

(

PARTITION p2001 start('2001-01-01'::date) END ('2002-01-01'::date),

PARTITION p2002 start('2002-01-01'::date) END ('2003-01-01'::date),

PARTITION p2003 start('2003-01-01'::date) END ('2004-01-01'::date)

)

;

CREATE TABLE public.order_log_1_prt_p2004 PARTITION OF public.order_log FOR VALUES FROM ('2004-01-01'::date) TO ('2005-01-01'::date);

CREATE TABLE public.order_log_1_prt_p2005 PARTITION OF public.order_log FOR VALUES FROM ('2005-01-01'::date) TO ('2006-01-01'::date);


SELECT schemaname, tablename, partitiontablename, partitiontype, partitionboundary

FROM gp_toolkit.gp_partitions

WHERE schemaname = 'public'

AND tablename = 'order_log'

;


--output

schemaname|tablename|partitiontablename |partitiontype|partitionboundary |

----------+---------+---------------------+-------------+------------------------------------------------+

public |order_log|order_log_1_prt_p2001|range |FOR VALUES FROM ('2001-01-01') TO ('2002-01-01')|

public |order_log|order_log_1_prt_p2002|range |FOR VALUES FROM ('2002-01-01') TO ('2003-01-01')|

public |order_log|order_log_1_prt_p2003|range |FOR VALUES FROM ('2003-01-01') TO ('2004-01-01')|

public |order_log|order_log_1_prt_p2004|range |FOR VALUES FROM ('2004-01-01') TO ('2005-01-01')|

public |order_log|order_log_1_prt_p2005|range |FOR VALUES FROM ('2005-01-01') TO ('2006-01-01')|


--Greenplum 7에서 파티션 Drop (파티션명으로 삭제)

ALTER TABLE public.order_log DROP PARTITION p2001;


--Greenplum 7에서 파티션 Drop (파티션 구간으로 삭제 - 삭제시 FROM의 값을 지정 )

ALTER TABLE public.order_log DROP PARTITION FOR ('2002-01-01');



SELECT schemaname, tablename, partitiontablename, partitiontype, partitionboundary

FROM gp_toolkit.gp_partitions

WHERE schemaname = 'public'

AND tablename = 'order_log'

;


--output

schemaname|tablename|partitiontablename |partitiontype|partitionboundary |

----------+---------+---------------------+-------------+------------------------------------------------+

public |order_log|order_log_1_prt_p2003|range |FOR VALUES FROM ('2003-01-01') TO ('2004-01-01')|

public |order_log|order_log_1_prt_p2004|range |FOR VALUES FROM ('2004-01-01') TO ('2005-01-01')|

public |order_log|order_log_1_prt_p2005|range |FOR VALUES FROM ('2005-01-01') TO ('2006-01-01')|




--##### 4. Default 파티션 Split 작업

DROP TABLE IF EXISTS public.order_log;

CREATE TABLE public.order_log

(

order_no int,

cust_no int,

prod_nm TEXT,

order_date date

)

WITH (appendonly=TRUE, compresstype=zstd, compresslevel=7)

DISTRIBUTED BY (order_no)

PARTITION BY RANGE (order_date)

(

PARTITION p2001 start('2001-01-01'::date) END ('2002-01-01'::date),

PARTITION p2002 start('2002-01-01'::date) END ('2003-01-01'::date),

PARTITION p2003 start('2003-01-01'::date) END ('2004-01-01'::date),

PARTITION p2004 start('2004-01-01'::date) END ('2005-01-01'::date),

PARTITION p2005 start('2005-01-01'::date) END ('2006-01-01'::date),

DEFAULT PARTITION pother

)

;


SELECT schemaname, tablename, partitiontablename, partitiontype, partitionboundary

FROM gp_toolkit.gp_partitions

WHERE schemaname = 'public'

AND tablename = 'order_log'

;


schemaname|tablename|partitiontablename |partitiontype|partitionboundary |

----------+---------+----------------------+-------------+------------------------------------------------+

public |order_log|order_log_1_prt_p2001 |range |FOR VALUES FROM ('2001-01-01') TO ('2002-01-01')|

public |order_log|order_log_1_prt_p2002 |range |FOR VALUES FROM ('2002-01-01') TO ('2003-01-01')|

public |order_log|order_log_1_prt_p2003 |range |FOR VALUES FROM ('2003-01-01') TO ('2004-01-01')|

public |order_log|order_log_1_prt_p2004 |range |FOR VALUES FROM ('2004-01-01') TO ('2005-01-01')|

public |order_log|order_log_1_prt_p2005 |range |FOR VALUES FROM ('2005-01-01') TO ('2006-01-01')|

public |order_log|order_log_1_prt_pother|range |DEFAULT |


ALTER TABLE public.order_log SPLIT DEFAULT PARTITION

START ('2006-01-01') INCLUSIVE END ('2007-01-01') EXCLUSIVE

INTO (PARTITION P2006, PARTITION POTHER)

;


SELECT schemaname, tablename, partitiontablename, partitiontype, partitionboundary

FROM gp_toolkit.gp_partitions

WHERE schemaname = 'public'

AND tablename = 'order_log'

;


schemaname|tablename|partitiontablename |partitiontype|partitionboundary |

----------+---------+----------------------+-------------+------------------------------------------------+

public |order_log|order_log_1_prt_p2001 |range |FOR VALUES FROM ('2001-01-01') TO ('2002-01-01')|

public |order_log|order_log_1_prt_p2002 |range |FOR VALUES FROM ('2002-01-01') TO ('2003-01-01')|

public |order_log|order_log_1_prt_p2003 |range |FOR VALUES FROM ('2003-01-01') TO ('2004-01-01')|

public |order_log|order_log_1_prt_p2004 |range |FOR VALUES FROM ('2004-01-01') TO ('2005-01-01')|

public |order_log|order_log_1_prt_p2005 |range |FOR VALUES FROM ('2005-01-01') TO ('2006-01-01')|

public |order_log|order_log_1_prt_p2006 |range |FOR VALUES FROM ('2006-01-01') TO ('2007-01-01')|

public |order_log|order_log_1_prt_pother|range |DEFAULT |






댓글 없음:

댓글 쓰기

Greenplum Disaster Recovery

Greenplum DR를 사용하면, 재해 발생 전 특정 복구 시점으로 복구 지원 Greenplum DR은 Full 백업/복구, Incremental 백업/복구, WAL 로그 기반으로 DR 기능 제공 Greenplum Disaster Recovery 지...