PostgreSQL 10.x Partitioning 0 0 5,845

by 지현명 [PostgreSQL 노하우/팁/자료] PostgreSQL Partition [2018.03.06 09:52:59]


PG10 파티션.sql (5,071Bytes)

--https://www.postgresql.org/docs/10/static/ddl-partitioning.html

-------------------------------------------------------------------------------
--RANGE 파티션 
--------------------------------------------------------------------------------

CREATE TABLE measurement (
    city_id         int not null,
    logdate         date not null,
    peaktemp        int,
    unitsales       int
) PARTITION BY RANGE (logdate);

--오류:  "measurement" 파티션된 테이블 대상으로 인덱스를 만들 수 없음
CREATE INDEX ON measurement (logdate);
--메인 부모 테이블에 인덱스를 만들 수 없다.

CREATE TABLE measurement_y2006m02 PARTITION OF measurement
FOR VALUES FROM ('2006-02-01') TO ( '2006-03-01');
--CHECK ( logdate >= DATE '2008-02-01' AND logdate < DATE '2008-03-01' );

CREATE TABLE measurement_y2006m03 PARTITION OF measurement
FOR VALUES FROM ('2006-03-01') TO ('2006-04-01');


CREATE INDEX ON measurement_y2006m02 (logdate);

CREATE INDEX ON measurement_y2006m03 (logdate);


--파티션 테이블을 메인 부모 테이블에서 분리 시키려면 DETACH
--DETACH 하면 조건절이 삭제 되면서 일반 테이블로 풀립니다.
--pgAdmin4에서도 일반 테이블로 보여집니다.
ALTER TABLE measurement DETACH PARTITION measurement_y2006m03;

--이거 때문에 다시 ATTACH하려면 조건절 다시 입력해야 합니다.
ALTER TABLE measurement ATTACH PARTITION measurement_y2006m03
FOR VALUES FROM ('2006-03-01') TO ('2006-04-01'); --이렇게 다시ATTACH하려면 조건을 입력해야 합니다. 

--DETACH하더라도 조건절을 유지 할줄 알았는데 그래서 ATTACH 할때 헛갈렸습니다. 조건절 다시 안쓰니까 에러나서...
--풀릴때 CHECK 라도 유지하고 다시 ATTACH할때 CHECK를 자동으로 삭제하면 될거 같은데..이거 메뉴얼 보니 수동으로 해야 하네요...

insert into measurement values (1, '2006-02-01', 1, 1),(2, '2006-03-01', 2, 2);

insert into measurement values (3, '2006-03-01', 1, 1);

select * from measurement; 

--show constraint_exclusion;

analyze  measurement_y2006m02;
analyze  measurement_y2006m03;

select * from measurement_y2006m03

--이렇게 하면 파티션 Pruning이 안됩니다.
--파티션 Pruning이 되게 하려면 파티션 조건하고 동일한 데이터 type으로 해야 합니다. 
explain (costs false)
select * from measurement
where logdate = to_date('20060301', 'YYYYMMDD')
--where logdate = DATE '2006-03-01'

explain (costs false)
select * from measurement
where logdate in (DATE '2006-02-01')

------------------------------------------------------------
--파티션 테이블의 통계정보 갱신
------------------------------------------------------------
VACUUM or analyze 은 파티션 각 테이블 별로 해야함.
 
 
 --파티션 range값을 다른 파티션 테이블로 변경할 경우 에러 발생
 select * from measurement
 where city_id = 1;

--에러발생
--파티션 키 값을 update하면 에러발생합니다. ms-sql과 다른점입니다.
--트리거로 이동하는 함수 작성해서 연결해 줘야 합니다.
update measurement
set
    logdate = '2006-03-01'
where city_id = 1;
 

------------------------------------------------------------
--PostgreSQL 파티션 Pruning
/*
 * NL 조인으로 수행되면 추가 조건 없이도 파티션 Pruning이 수행된다.
 * Hash 조인으로 수행되면 추가 조건을 반드시 입력해야 한다. 
 * 따라서, 쿼리 작성 후에 Explain 결과 확인 및 추가 조건을 입력할 필요가 있다.
 */
------------------------------------------------------------
create table p1 (
    c1        integer,
    logdate   date,
    dummy     char(10)
) partition by range (logdate); 

create table p2 (
    c1        integer,
    logdate   date,
    amount    integer,
    dummy     char(10)
) partition by range (logdate);

create table p1_y201701 partition of p1 for values from ('2017-01-01') to ('2017-02-01');
create table p1_y201702 partition of p1 for values from ('2017-02-01') to ('2017-03-01');
create table p1_y201703 partition of p1 for values from ('2017-03-01') to ('2017-04-01');
create table p1_y201704 partition of p1 for values from ('2017-04-01') to ('2017-05-01');

create table p2_y201701 partition of p2 for values from ('2017-01-01') to ('2017-02-01');
create table p2_y201702 partition of p2 for values from ('2017-02-01') to ('2017-03-01');
create table p2_y201703 partition of p2 for values from ('2017-03-01') to ('2017-04-01');
create table p2_y201704 partition of p2 for values from ('2017-04-01') to ('2017-05-01');


set enable_nestloop=on; 
set enable_mergejoin=off;
set enable_hashjoin=off;

explain (costs false)
select count(*)
from   p1 a inner join  p2 b using (logdate)
where 1=1  
and    a.c1      = b.c1
and    a.logdate between DATE '2017-01-15' and DATE '2017-01-31'
and    b.logdate between DATE '2017-01-15' and DATE '2017-01-31'
;


explain (analyse, buffers)
select count(*)
from   p1 a inner join  p2 b using (logdate)
where 1=1  
--a.logdate = b.logdate 
and    a.c1      = b.c1
and    a.logdate between DATE '2017-01-15' and DATE '2017-01-31'
and    b.logdate between DATE '2017-01-15' and DATE '2017-01-31'
;
 
-------------------------------------------------------------------------------
--List 파티션 
--------------------------------------------------------------------------------
create table list_p1 
(
    c1       integer,
    code     integer,
    dummy    char(100)
) PARTITION BY LIST  (c1);


CREATE TABLE list_p1_code1
    PARTITION OF list_p1 for values in(1);


CREATE TABLE list_p1_code2
    PARTITION OF list_p1 for values in(2);


insert into list_p1 values(3, 1, 'test')

select * from list_p1_code2

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입