파티셔닝 (Partitioning)은 태이블과 인텍스 데이터를 파티션(Partition) 단위로 나누어 저장하는 것을 말한다.
테이블을 파티셔닝하면 하나의 테이블일지라도 파티션 거에 따라 물리적으로는 별도의 세그먼트에 데이터가 저장되며 인텍스도 마찬가지다.
● 파티셔닝이 필요한 이유
① 관리적 측면 : 파티션 단위 백업,추가,삭제 ,변경
② 성능적 측면 : 파티션 단위 조회 및 DML수행
h3.(1) 파티셔닝 기본 구조
파티셔닝 기능은 8버전부터 지원이 되었으며 그전 까지는 View로 직접 만들어서 관리를 하였다 이를 '수동파티셔닝'이라고 한다.
-- 파티션 뷰를 정의할 때 사용할 Base 테이블을 만든다.
SQL> create table p1 as select * from emp where deptno = 10;
테이블이 생성되었습니다.
SQL> create table p2 as select * from emp where deptno = 20;
테이블이 생성되었습니다.
SQL> create table p3 as select * from emp where deptno = 30;
테이블이 생성되었습니다.
-- 체크 제약을 반드시 설정해야 함
SQL> alter table p1 add constraint c_deptno_10 check(deptno < 20);
테이블이 변경되었습니다.
SQL> alter table p2 add constraint c_deptno_20 check(deptno >= 20 and deptno < 30);
테이블이 변경되었습니다.
SQL> alter table p3 add constraint c_deptno_30 check(deptno >= 30 and deptno < 40);
테이블이 변경되었습니다.
SQL> create index p1_empno_idx on p1(empno);
인덱스가 생성되었습니다.
SQL> create index p2_empno_idx on p2(empno);
인덱스가 생성되었습니다.
SQL> create index p3_empno_idx on p3(empno);
인덱스가 생성되었습니다.
SQL> analyze table p1 compute statistics;
테이블이 분석되었습니다.
SQL> analyze table p2 compute statistics;
테이블이 분석되었습니다.
SQL> analyze table p3 compute statistics;
테이블이 분석되었습니다.
-- 파티션 뷰를 정의한다.
SQL> create or replace view partition_view
2 as
3 select * from p1
4 union all
5 select * from p2
6 union all
7 select * from p3 ;
뷰가 생성되었습니다.
SQL> explain plan for
2 select * from partition_view
3 where deptno = :deptno ;
해석되었습니다.
SQL> @?/rdbms/admin/utlxpls
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1236824284
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5 | 170 | 4 (0)| 00:00:01 |
| 1 | VIEW | PARTITION_VIEW | 5 | 170 | 4 (0)| 00:00:01 |
| 2 | UNION-ALL PARTITION| | | | | |
|* 3 | TABLE ACCESS FULL | P1 | 3 | 93 | 3 (0)| 00:00:01 |
|* 4 | TABLE ACCESS FULL | P2 | 5 | 155 | 3 (0)| 00:00:01 |
|* 5 | TABLE ACCESS FULL | P3 | 6 | 204 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter("DEPTNO"=TO_NUMBER(:DEPTNO))
4 - filter("DEPTNO"=TO_NUMBER(:DEPTNO))
5 - filter("DEPTNO"=TO_NUMBER(:DEPTNO))
19 개의 행이 선택되었습니다.
SQL> explain plan for
2 select * from partition_view
3 where deptno = 10;
해석되었습니다.
SQL> @?/rdbms/admin/utlxpls
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 180990235
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5 | 170 | 4 (0)| 00:00:01 |
| 1 | VIEW | PARTITION_VIEW | 5 | 170 | 4 (0)| 00:00:01 |
| 2 | UNION-ALL PARTITION| | | | | |
|* 3 | TABLE ACCESS FULL | P1 | 3 | 93 | 3 (0)| 00:00:01 |
|* 4 | FILTER | | | | | |
|* 5 | TABLE ACCESS FULL| P2 | 1 | 31 | 3 (0)| 00:00:01 |
|* 6 | FILTER | | | | | |
|* 7 | TABLE ACCESS FULL| P3 | 1 | 34 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter("DEPTNO"=10)
4 - filter(NULL IS NOT NULL)
5 - filter("DEPTNO"=10)
6 - filter(NULL IS NOT NULL)
7 - filter("DEPTNO"=10)
23 개의 행이 선택되었습니다.
SQL> create table partition_table
2 partition by range(deptno) --파티션 뷰의 Base 태이블에 체크 제약을 설정히는 것과 같은 역할
3 ( partition p1 values less than(20) --세개의 세그먼트가 생성되므로 앞에서 파티션 뷰를 정의할 때와 구조적으로 같다.
4 , partition p2 values less than(30)
5 , partition p3 values less than(40)
6 )
7 as
8 select * from emp ;
테이블이 생성되었습니다.
SQL> create index ptable_empno_idx on partition_table(empno) LOCAL; --Local옵션으로 파티션 뷰 Base 테이블에 각각 인덱스를
인덱스가 생성되었습니다. 만든 것과 같은 모습이다.
h3.(2)Range 파티셔닝
-- Range 파티셔닝
create table 주문( 주문번호 number, 주문일자 varchar2(8), 고객id varchar2(5) )
partition by range(주문일자) (
partition p2009_q1 values less than('20090401')
, partition p2009_q2 values less than('20090701')
, partition p2009_q3 values less than('20091001')
, partition p2009_q4 values less than('20100101')
, partition p2010_q1 values less than('20100401')
, partition p9999_mx values less than( MAXVALUE )
);
h3.(3)Hash 파티셔닝
① 파티션 키에 해시 함수를 적용한 결과 값이 같은 레코드를 같은 파티션 세그먼트에 저장해 두는 방식이며,주로 고객 ID처럼
변별력이 좋고 데이터 분포가 고른 컬럼을 파티션 기준 컬럼으로 선정해야 효과적이다.
② 알고리즘 특성상 등치(=) 조건 또는 IN-List 조건으로 검색할 때만 파티션 Pruning이 작동한다.
③ 테이블 파티셔닝 여부를 결정할 때는 데이터가 얼마나 고르게 분산될 수 있느냐가 가장 중요한 관심사항이다.
(특히,해시 파티셔닝은 파티션 개수만 사용자가 결정하고 데이터를 분산시키는 해싱 알고리즘은 오라클에 의해 결정되기 때문)
④ 특정 파티션에 데이터가 몰리지 않도록 하려면 파티션 개수를 2의 제곱,2, 4, 8, 16 등) 으로 설정할 것을 권고
SQL> create table t_hash1
2 (c1 number, c2 varchar2(10))
3 partition by hash (c1)
4 (partition p1 tablespace users,
5 partition p2 tablespace users);
테이블이 생성되었습니다.
데이터가 모든파티션에 고르게 분산돼 있다면 특히 각 파티션이 서로 다른 디바이스에 저장돼 있다면 병렬 I/O 성능을 극대화할 수 있다.
반대로 말하면 데이터가 고르게 분산되지 않을 때는 병렬 쿼리 효과가반감된다.
h3.(4) List 파티셔닝
① 오라클 9i 버전부터 제공되기 시작
② 사용자에 의해 미리 정해진 그룹핑 기준에 따라 데이터를분할 저장하는 방식
③ Range 파티션에선 값의 순서에 따라 저장할 파티션이 결정되지만, 리스트 파티션에서는 순서와 상관없이 불연속적인 값의 목록으로써 결정
④해시 파티션과 비교하면 해시 파티션은 오라클이 정한 해시 알고리즘에 따라 임의로 분할하는 구조인 반면 리스트 파티션은 사용자가
정의한논리적인 그룹에 따라분할
⑤ Range, 해시 파티셔닝과 달리 리스트 파티셔닝에는 단일 컬럼으로만 파티션 키를 지정할 수 있다. 그리고 Range 파티션에 maxvalue 파티션을
반드시 생성하라고 권고한 것과 같은 이유로,리스트 파티션에도 default 파티션을 생성해 두어야 안전하다
create table 인터넷매물( 물건코드varchar2(5), 지역?류varchar2(4) )
partition by list(지역?류)
(partition p_지역1 values ('서울'),
partition p_지역2 values ('경기', '인천'),
partition p_지역3 values ('부산', '대구', '대전', '광주'),
partition p_기타values (DEFAULT) ) ;
h3.(4) 결합 파티셔닝
h5.Range + 해시 결합 파티셔닝
create table 주문( 주문번호number, 주문일자varchar2(8), 고객id varchar2(5) )
partition by range(주문일자)
subpartitionby hash(고객id) subpartitions8
( partition p2009_q1 values less than('20090401'),
partition p2009_q2 values less than('20090701'),
partition p2009_q3 values less than('20091001'),
partition p2009_q4 values less than('20100101'),
partition p2010_q1 values less than('20100401'),
partition p9999_mx values less than( MAXVALUE ));
h5.Range + 리스트 결합 파티셔닝
create table 판매 ( 판매점 varchar2(10), 판매일자 varchar2(8) )
partition by range(판매일자)
subpartition by list(판매점)
subpartition template
( subpartition lst_01 values ('강남지점', '강북지점', '강서지점', '강동지점')
, subpartition lst_02 values ('부산지점', '대전지점')
, subpartition lst_03 values ('인천지점', '제주지점', '의정부지점')
, subpartition lst_99 values ( DEFAULT ) )
( partition p2009_q1 values less than('20090401')
, partition p2009_q2 values less than('20090701')
, partition p2009_q3 values less than('20091001')
, partition p2009_q4 values less than('20100101') );
h5.기타 결합 파티셔닝
11g부터 다양한 결합 파티셔닝이 아래와 같이 가능해 졌다.
① Range-Range
② 리스트-해시
③ 리스트-리스트
④ 리스트-Range
h5.11g에 추가된 파티션 유형
① Reference 파티션
부모 테이블 파티션 키를 이용해 자식 테이블을 파티셔닝하는기능
Create table 상품 {
상품번호 numberNOT NULL PRIMARY KEY
, 상품명 varchar2(50) not null
, 현재가격 number not null
, 상품대분류 varchar2(4) not null
, 등록일시 date not null
)
Partition by list(상품대분류) (
Partition p1 values ('의류')
,partition p2 values ('식품')
,partition p3 values ('가전')
,partition 4 values ('컴퓨터')
);
create table 일별상품거래 (
상품번호 number NOT NULL
, 거래일자 varchar2(8)
, 판매가격 number
, 판매수량 number
, 판매금액 number
, constraint 일별상품거래_fk foreign key(상품번호) references 상품
)
partition by reference (일별상품거래_fk);
② Interval 파티셔닝
11g 부터는 Range 파티션을 생성할 대 아래와 같이 interval, 기준을 정의함으로써 정해진 간격으로 파티션이 자동 추가되도록 할 수 있다.
create table 주문일자 (주문번호 number, 주문일시 date, ... )
partition by range(주문일시) INTERVAL(NUMTOYMINTERVAL(1, 'MONTH'))
(
, partition p200907 values less than(to_date('2009/08/01', 'yyyy/mm/dd'))
, partition p200908 values less than(to_date('2009/09/01', 'yyyy/mm/dd'))
, partition p200909 values less than(to_date('2009/10/01', 'yyyy/mm/dd'))
, partition p200910 values less than(to_date('2009/11/01', 'yyyy/mm/dd'))
);
create table 고객 (고객번호 number, 고객명 varchar2(20), ... )
partition by range(고객번호) INTERVAL (100000)
( partition p_cust1 values less than ( 100001 )
, partition p_cust2 values less than ( 200001 )
, partition p_cust3 values less than ( 300001 )
) ;