# 요약
  ■ Partition
Partitioning Pruning

■ 수동 파티셔닝(Manual Partitioning)
Partitioning Pruning

■ Range Partition
less than
maxvalue
Interval

■ Hash Partition
hash() partitions 4

■ List Partition

■ Composite Partition
# Range - Hash Partition
# Range - List partition

# Logging Mode 상태 확인

# Partition 나누기 : Split
# Partition 추가 : Add
# Partition 이름 변경 : Rename
# Partition 삭제 : Drop
# Partition 내 Data 삭제: Truncate
# 파티션 키컬럼 값 수정 : Flashback 
# Maxvalue Partition 추가
# Partition Merge
# Partition Exchange (데이터 교환)
# Partition Table 통계 수집  : granularity => 'auto'
# Data Pump

------------------------------
range   날짜 이력성
hash    동시 insert
list    값 목록

 

 


 

 

■ Partition
- 테이블 또는 인덱스를 파티션 단위로 나눠서 저장하는 것
- 테이블 파티션하면 하나의 테이블일지라도 파티션 키에 따라 물리적으로 별도의 세그먼트에 데이터가 저장된다.
- 관리적 측면으로 보면 보관주기가 지난 데이터들을 별도로 백업하고 지우는 일이 아주 쉬워진다.
- 성능적 측면으로 파티셔닝하지 않은 테이블이 대용량일 때 인덱스를 이용해서 데이터를 검색하더라도 데이터의 양이 
많아서 인덱스를 이용해 건건히 테이블 액세스하는 방식(Random I/O)은 일정량이 넘는 순간 Full Table Scan 보다 더 못한
결과가 나온다. 그렇다고 Full Table Scan도 부담스럽다면 바로 그때 파티션을 나누면 Full Table Scan 을 하더라도 일부
파티션 세그먼트만 읽고 멈출 수 있다.(Partition Pruning)

> Partition 기능은 엔터프라이즈 급 + 별도 라이센스 필요하다

 

 


 

 

--- Create Table
HR@ora11g> create table hr.p10 as select * from hr.employees where 1 = 2;

Table created.

HR@ora11g> create table hr.p12 as select * from hr.employees where 1 = 2;

Table created.

HR@ora11g> create table hr.p13 as select * from hr.employees where 1 = 2;

Table created.

--- Add Constraint : Check
HR@ora11g> alter table hr.p10 add constraint c_deptno_10 check(department_id < 20);

Table altered.

HR@ora11g> alter table hr.p12 add constraint c_deptno_20 check(department_id >= 20 and department_id < 30);

Table altered.

HR@ora11g> alter table hr.p13 add constraint c_deptno_30 check(department_id >= 30 and department_id < 40);

Table altered.

--- Insert
HR@ora11g> insert into hr.p10 select * from hr.employees where department_id < 20;

1 row created.

HR@ora11g> insert into hr.p12 select * from hr.employees where department_id >= 20 and department_id < 30;

2 rows created.

HR@ora11g> insert into hr.p13 select * from hr.employees where department_id >= 30 and department_id < 40;

6 rows created.


HR@ora11g> commit;

Commit complete.

 

 

 

 

■ 수동 파티셔닝(Manual Partitioning)
- 7버전까지는 파티션 테이블이 제공되지 않았기 때문에 파티션 뷰를 통해 파티션 기능을 구현했다.
- 파티션 뷰의 핵심기능은 뷰 쿼리에 사용된 조건절에 부합하는 테이블만 읽는다. 이를 Partitioning Pruning이라고 한다.

--- Create View
HR@ora11g> create or replace view hr.emp_partition
           as 
           select * from hr.p10
           union all
           select * from hr.p12
           union all
           select * from hr.p13;

View created.


HR@ora11g> HR@ora11g> select * from hr.emp_partition;

9 rows selected.


--- 통계 수집
HR@ora11g> exec dbms_stats.gather_table_stats('hr','p10')

PL/SQL procedure successfully completed.

HR@ora11g> exec dbms_stats.gather_table_stats('hr','p12')

PL/SQL procedure successfully completed.

HR@ora11g> exec dbms_stats.gather_table_stats('hr','p13')

PL/SQL procedure successfully completed.

 

 

 

# WHERE department_id = 10

HR@ora11g> select /*+ gather_plan_statistics */ * from emp_partition where department_id = 10;


HR@ora11g> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

------------------------------------------------------------------------------------------------
| Id  | Operation            | Name          | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |               |      1 |        |      1 |00:00:00.01 |       6 |
|   1 |  VIEW                | EMP_PARTITION |      1 |      3 |      1 |00:00:00.01 |       6 |
|   2 |   UNION-ALL          |               |      1 |        |      1 |00:00:00.01 |       6 |
|*  3 |    TABLE ACCESS FULL | P10           |      1 |      1 |      1 |00:00:00.01 |       6 |
|*  4 |    FILTER            |               |      1 |        |      0 |00:00:00.01 |       0 |
|*  5 |     TABLE ACCESS FULL| P12           |      0 |      1 |      0 |00:00:00.01 |       0 |
|*  6 |    FILTER            |               |      1 |        |      0 |00:00:00.01 |       0 |
|*  7 |     TABLE ACCESS FULL| P13           |      0 |      1 |      0 |00:00:00.01 |       0 |
------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("DEPARTMENT_ID"=10)
   4 - filter(NULL IS NOT NULL)
   5 - filter("DEPARTMENT_ID"=10)
   6 - filter(NULL IS NOT NULL)
   7 - filter("DEPARTMENT_ID"=10)

> 10번 부서 : Only P10 Table + Check 제약조건



# WHERE department_id = 20

HR@ora11g> select /*+ gather_plan_statistics */ * from emp_partition where department_id = 20;


HR@ora11g> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

------------------------------------------------------------------------------------------------
| Id  | Operation            | Name          | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |               |      1 |        |      2 |00:00:00.01 |       7 |
|   1 |  VIEW                | EMP_PARTITION |      1 |      3 |      2 |00:00:00.01 |       7 |
|   2 |   UNION-ALL          |               |      1 |        |      2 |00:00:00.01 |       7 |
|*  3 |    FILTER            |               |      1 |        |      0 |00:00:00.01 |       0 |
|*  4 |     TABLE ACCESS FULL| P10           |      0 |      1 |      0 |00:00:00.01 |       0 |
|*  5 |    TABLE ACCESS FULL | P12           |      1 |      2 |      2 |00:00:00.01 |       7 |
|*  6 |    FILTER            |               |      1 |        |      0 |00:00:00.01 |       0 |
|*  7 |     TABLE ACCESS FULL| P13           |      0 |      1 |      0 |00:00:00.01 |       0 |
------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter(NULL IS NOT NULL)
   4 - filter("DEPARTMENT_ID"=20)
   5 - filter("DEPARTMENT_ID"=20)
   6 - filter(NULL IS NOT NULL)
   7 - filter("DEPARTMENT_ID"=20)

 


# 바인더 변수 사용 시

HR@ora11g> var b_dept_id number
HR@ora11g> exec :b_dept_id := 30

PL/SQL procedure successfully completed.


HR@ora11g> select /*+ gather_plan_statistics */ * from emp_partition
           where department_id = :b_dept_id;


HR@ora11g> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

-----------------------------------------------------------------------------------------------
| Id  | Operation           | Name          | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |               |      1 |        |      6 |00:00:00.01 |      19 |
|   1 |  VIEW               | EMP_PARTITION |      1 |      3 |      6 |00:00:00.01 |      19 |
|   2 |   UNION-ALL         |               |      1 |        |      6 |00:00:00.01 |      19 |
|*  3 |    TABLE ACCESS FULL| P10           |      1 |      1 |      0 |00:00:00.01 |       6 |
|*  4 |    TABLE ACCESS FULL| P12           |      1 |      1 |      0 |00:00:00.01 |       6 |
|*  5 |    TABLE ACCESS FULL| P13           |      1 |      6 |      6 |00:00:00.01 |       7 |
-----------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("DEPARTMENT_ID"=:B_DEPT_ID)
   4 - filter("DEPARTMENT_ID"=:B_DEPT_ID)
   5 - filter("DEPARTMENT_ID"=:B_DEPT_ID)

> 바인더변수는 VIEW를 이용하는 Partitioning Pruning 작동하지 않아 I/O 과다 발생
> 조건제어문을 사용하는게 좋다.



# WHERE department_id = 30 AND employee_id = 115

HR@ora11g> select /*+ gather_plan_statistics */ * from emp_partition 
           where department_id = 30 and employee_id = 115;


HR@ora11g> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

------------------------------------------------------------------------------------------------
| Id  | Operation            | Name          | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |               |      1 |        |      1 |00:00:00.01 |       7 |
|   1 |  VIEW                | EMP_PARTITION |      1 |      1 |      1 |00:00:00.01 |       7 |
|   2 |   UNION-ALL          |               |      1 |        |      1 |00:00:00.01 |       7 |
|*  3 |    FILTER            |               |      1 |        |      0 |00:00:00.01 |       0 |
|*  4 |     TABLE ACCESS FULL| P10           |      0 |      1 |      0 |00:00:00.01 |       0 |
|*  5 |    FILTER            |               |      1 |        |      0 |00:00:00.01 |       0 |
|*  6 |     TABLE ACCESS FULL| P12           |      0 |      1 |      0 |00:00:00.01 |       0 |
|*  7 |    TABLE ACCESS FULL | P13           |      1 |      1 |      1 |00:00:00.01 |       7 |
------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter(NULL IS NOT NULL)
   4 - filter(("EMPLOYEE_ID"=115 AND "DEPARTMENT_ID"=30))
   5 - filter(NULL IS NOT NULL)
   6 - filter(("EMPLOYEE_ID"=115 AND "DEPARTMENT_ID"=30))
   7 - filter(("EMPLOYEE_ID"=115 AND "DEPARTMENT_ID"=30))
   
> department_id : Check 제약조건

 

 

# WHERE department_id = 30 AND demployee_id = 115

--- Create Unique Index
HR@ora11g> create unique index hr.p13_id_ix on hr.p13(employee_id);

Index created.

--- Add Primary Key
HR@ora11g> alter table hr.p13 add constraint p13_id_pk primary key(employee_id) using index hr.p13_id_ix;

Table altered.


HR@ora11g> select /*+ gather_plan_statistics */ * from emp_partition 
           where department_id = 30 and employee_id = 115;


HR@ora11g> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

---------------------------------------------------------------------------------------------------------
| Id  | Operation                     | Name          | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
---------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |               |      1 |        |      1 |00:00:00.01 |       2 |
|   1 |  VIEW                         | EMP_PARTITION |      1 |      3 |      1 |00:00:00.01 |       2 |
|   2 |   UNION-ALL                   |               |      1 |        |      1 |00:00:00.01 |       2 |
|*  3 |    FILTER                     |               |      1 |        |      0 |00:00:00.01 |       0 |
|*  4 |     TABLE ACCESS FULL         | P10           |      0 |      1 |      0 |00:00:00.01 |       0 |
|*  5 |    FILTER                     |               |      1 |        |      0 |00:00:00.01 |       0 |
|*  6 |     TABLE ACCESS FULL         | P12           |      0 |      1 |      0 |00:00:00.01 |       0 |
|*  7 |    TABLE ACCESS BY INDEX ROWID| P13           |      1 |      1 |      1 |00:00:00.01 |       2 |
|*  8 |     INDEX UNIQUE SCAN         | P13_ID_IX     |      1 |      1 |      1 |00:00:00.01 |       1 |
---------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter(NULL IS NOT NULL)
   4 - filter(("DEPARTMENT_ID"=30 AND "EMPLOYEE_ID"=115))
   5 - filter(NULL IS NOT NULL)
   6 - filter(("EMPLOYEE_ID"=115 AND "DEPARTMENT_ID"=30))
   7 - filter("DEPARTMENT_ID"=30)
   8 - access("EMPLOYEE_ID"=115)

> department_id : Check 제약조건
> employee_id : unique Index + primary key

 

 

 

 

# 제약조건 삭제 후 인덱스 삭제 하자.

HR@ora11g> drop index hr.p13_id_ix;

ORA-02429: cannot drop index used for enforcement of unique/primary key

↓

HR@ora11g> alter table hr.p13 drop constraint p13_id_pk;

Table altered.

HR@ora11g> drop index hr.p13_id_ix;

Index dropped.






■ Range Partition
- 8버전부터 제공
- 이력성 데이터 조회에 유리
- 여러 컬럼을 파티션키로 지정 가능(최대 16)
- maxvalue 파티션을 생성
- less than 사용

# 날짜로 파티션 지정

HR@ora11g> create table hr.emp_year
           partition by range(hire_date)
           (partition p2004 values less than (to_date('2005-01-01','yyyy-mm-dd')),
            partition p2005 values less than (to_date('2006-01-01','yyyy-mm-dd')),
            partition p2006 values less than (to_date('2007-01-01','yyyy-mm-dd')),
            partition pmax values less than (maxvalue)
           )
           as select employee_id, last_name, salary, hire_date, department_id 
              from hr.employees;
              
Table created.

> range + less than 세트
> range(hire_date)     : 기준 컬럼 키
> less than(to_date()) : ~ 이전
> less than(maxvalue)  : 이후 자료, 안만들면 데이터 누락 및 에러


HR@ora11g> select partition_name, high_value, tablespace_name, num_rows, blocks, avg_row_len
           from user_tab_partitions
           where table_name = 'EMP_YEAR';

PARTITION_NAME HIGH_VALUE                                                                       TABLESPACE_NAME
-------------- -------------------------------------------------------------------------------- ---------------
P2004          TO_DATE(' 2005-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA USERS
P2005          TO_DATE(' 2006-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA USERS
P2006          TO_DATE(' 2007-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA USERS
PMAX           MAXVALUE                                                                         USERS

> less than을 사용하니 해당 날짜 이전까지라고 생각해야한다.


HR@ora11g> select partitioning_type, partition_count 
           from user_part_tables where table_name = 'EMP_YEAR';

PARTITION PARTITION_COUNT
--------- ---------------
RANGE                   4


HR@ora11g> select * from user_part_key_columns where name = 'EMP_YEAR';

NAME                                          OBJEC COLUMN_NAME          COLUMN_POSITION
--------------------------------------------- ----- -------------------- ---------------
EMP_YEAR                                      TABLE HIRE_DATE                          1


HR@ora11g> select * from hr.emp_year;

107 rows selected.

HR@ora11g> select * from hr.emp_year partition(p2004);

24 rows selected.

HR@ora11g> select * from hr.emp_year partition(p2005);

29 rows selected.

HR@ora11g> select * from hr.emp_year partition(p2006);

24 rows selected.

HR@ora11g> select * from hr.emp_year partition(pmax);

30 rows selected.



# MaxValue 생략 시 나머지 데이터를 넣을 파티션이 없으면 생성불가

HR@ora11g> drop table hr.emp_year purge;

Table dropped.


HR@ora11g> create table hr.emp_year
           partition by range(hire_date)
           (partition p2004 values less than (to_date('2005-01-01','yyyy-mm-dd')),
            partition p2005 values less than (to_date('2006-01-01','yyyy-mm-dd')),
            partition p2006 values less than (to_date('2007-01-01','yyyy-mm-dd')),
            partition pmax values less than (maxvalue)
           )
           as
           select employee_id, last_name, salary, hire_date, department_id from hr.employees;

ORA-14400: inserted partition key does not map to any partition

 

 

 

 

# Range 옵션 : Interval Partitioning (11g)

- 기준을 정의함으로써 정해진 간격으로 파티션이 자동 추가되도록 할 수 있다.

HR@ora11g> create table hr.emp_year
           partition by range(hire_date) interval(numtoyminterval(1,'year'))
           (partition p2004 values less than (to_date('2005-01-01','yyyy-mm-dd')),
            partition p2005 values less than (to_date('2006-01-01','yyyy-mm-dd')),
            partition p2006 values less than (to_date('2007-01-01','yyyy-mm-dd'))
           )
           as select employee_id, last_name, salary, hire_date, department_id from hr.employees;

Table created.

> interval(numtoyminterval(1,'year')) : 1년마다


HR@ora11g> select partition_name, high_value, tablespace_name, interval
           from user_tab_partitions
           where table_name = 'EMP_YEAR';

PARTITION_NAME  HIGH_VALUE                                                                       TABLESPACE_NAME INTERVAL
--------------- -------------------------------------------------------------------------------- --------------- --------
P2004           TO_DATE(' 2005-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA USERS           NO
P2005           TO_DATE(' 2006-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA USERS           NO
P2006           TO_DATE(' 2007-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA USERS           NO
SYS_P41         TO_DATE(' 2008-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA USERS           YES
SYS_P42         TO_DATE(' 2009-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA USERS           YES

> SYS_P41, SYS_P42, ... 1년단위로 계속 생성된다.


HR@ora11g> select * from hr.emp_year;

107 rows selected.

HR@ora11g> select * from hr.emp_year partition(p2004);

24 rows selected.

HR@ora11g> select * from hr.emp_year partition(p2005);

29 rows selected.

HR@ora11g> select * from hr.emp_year partition(p2006);

24 rows selected.

HR@ora11g> select * from hr.emp_year partition(SYS_P41);

19 rows selected.

HR@ora11g> select * from hr.emp_year partition(SYS_P42);

11 rows selected.


HR@ora11g> select partitioning_type, partition_count from user_part_tables where table_name = 'EMP_YEAR';

PARTITION PARTITION_COUNT
--------- ---------------
RANGE             1048575






■ Hash Partition
- 8i 버전 제공
- Partition Key 값에 해시 함수를 적용하여 데이터를 분할하는 방식
- 중복성보다는 유일키 값으로 키값을 정하자.
- 데이터 분포가 고른 컬럼을 파티션 컬럼으로 선정하는게 좋다.
- 파티션 개수는 2의 제곱(2,4,8,16,32,...)으로 하는 이유는 특정 파티션에 몰리지않도록 하기위해서다.
- 조건절 = , in 조건을 검색할 때만 Partition Pruning 기능이 수행된다.
- 병렬쿼리 성능 향상뿐 아니라 동시에 입력이 많은 대용량 테이블이나 인덱스에 발생하는 경합을 줄일 목적으로
해시 파티셔닝을 사용한다.

> 동시 insert에 대한 성능 향상, 분산 목적

예) 주문테이블에 주문번호에 인덱스 걸려있다?
-> 인덱스는 squence -> leaf block에 경합 발생 -> EVENT : Buffer Busy Waits

-> 데이터 흩어지게 해야한다 -> hash partition 활용

    : select문 처리단계 흐름 참고

# 파티션을 4개로 생성

HR@ora11g> create table hr.emp_hash
           partition by hash(employee_id) partitions 4
           as select employee_id, last_name, salary, department_id from hr.employees;

Table created.


HR@ora11g> select partition_name, high_value, tablespace_name
           from user_tab_partitions
           where table_name = 'EMP_HASH';

PARTITION_NAME  HIGH_VALUE  TABLESPACE_NAME
--------------- ----------- ---------------
SYS_P43                     USERS
SYS_P44                     USERS
SYS_P45                     USERS
SYS_P46                     USERS


HR@ora11g> select partitioning_type, partition_count from user_part_tables where table_name = 'EMP_HASH';

PARTITION PARTITION_COUNT
--------- ---------------
HASH                    4


HR@ora11g> select * from user_part_key_columns where name = 'EMP_HASH';

NAME                                          OBJEC COLUMN_NAME          COLUMN_POSITION
--------------------------------------------- ----- -------------------- ---------------
EMP_HASH                                      TABLE EMPLOYEE_ID                        1


HR@ora11g> select * from hr.emp_hash partition(SYS_P43);

25 rows selected.

HR@ora11g> select * from hr.emp_hash partition(SYS_P44);

32 rows selected.

HR@ora11g> select * from hr.emp_hash partition(SYS_P45);

31 rows selected.

HR@ora11g> select * from hr.emp_hash partition(SYS_P46);

19 rows selected.






■ List Partition
- 9i 버전부터 제공
- 미리정해진 그룹을 기준으로 데이터를 분할, 값 목록
- 단일 컬럼만 가능

HR@ora11g> create table hr.emp_list
           partition by list(department_id)
           (partition p_dept_1 values(10,20,30,40),
            partition p_dept_2 values(50),
            partition p_dept_3 values(60,70,80,90,100,110),
            partition p_dept_4 values(default)
           )
           as select employee_id, last_name, salary, department_id from hr.employees;

Table created.

> default : 그 외 데이터


HR@ora11g> select partition_name, high_value, tablespace_name
           from user_tab_partitions
           where table_name = 'EMP_LIST';

PARTITION_NAME  HIGH_VALUE                   TABLESPACE_NAME
--------------- ---------------------------- ---------------
P_DEPT_1        10, 20, 30, 40               USERS
P_DEPT_2        50                           USERS
P_DEPT_3        60, 70, 80, 90, 100, 110     USERS
P_DEPT_4        default                      USERS


HR@ora11g> select partitioning_type, partition_count 
           from user_part_tables where table_name = 'EMP_LIST';

PARTITION PARTITION_COUNT
--------- ---------------
LIST                    4


HR@ora11g> select * from user_part_key_columns where name = 'EMP_LIST';

NAME                                          OBJECT_TYPE   COLUMN_NAME          COLUMN_POSITION
--------------------------------------------- ------------- -------------------- ---------------
EMP_LIST                                      TABLE         DEPARTMENT_ID                      1






■ Composite Partition (조합 파티션)
- 서브 파티션마다 세그먼트를 하나씩 할당하고 서브 파티션 단위로 데이터를 저장
- 주 파티션 키에 따라 1차적으로 데이터를 분배하고 서브 파티션 키에 따라 최종적으로 저장할 위치(세그먼트)를 결정하다.

Range - Hash Partition  (8i)
Range - List Partition  (9i)
Range - Range Partition (11g)
List - Hash Partition   (11g)
List - List Partition   (11g)
List - Range Partiton   (11g)

 

 

# Range - Hash Partition

HR@ora11g> create table hr.emp_comp
           partition by range(salary)				
           subpartition by hash(employee_id) subpartitions 4
           (partition p4999 values less than (5000),
            partition p9999 values less than (10000),
            partition p19999 values less than (20000),
            partition pmax values less than (maxvalue)
           )
           as select employee_id, last_name, salary, department_id from hr.employees;

Table created.

> range(salary)     : 급여를 금액 구간으로 분할 후 각 파티션 내  
> hash(employee_id) : 사번번호를 4분할 분산


--- 테이블 내 파티션 개수
HR@ora11g> select partitioning_type, partition_count, subpartitioning_type, def_subpartition_count
           from user_part_tables where table_name = 'EMP_COMP';

PARTITION PARTITION_COUNT SUBPARTIT DEF_SUBPARTITION_COUNT
--------- --------------- --------- ----------------------
RANGE                   4 HASH                           4


--- 주 파티션 컬럼 정보
HR@ora11g> select * from user_part_key_columns where name = 'EMP_COMP';

NAME                                          OBJECT_TYPE   COLUMN_NAME          COLUMN_POSITION
--------------------------------------------- ------------- -------------------- ---------------
EMP_COMP                                      TABLE         SALARY                             1


--- 주 파티션 정보
HR@ora11g> select partition_name, high_value, tablespace_name
           from user_tab_partitions
           where table_name = 'EMP_COMP';

PARTITION_NAME  HIGH_VALUE    TABLESPACE_NAME
--------------- ------------- ---------------
P4999           5000          USERS
P9999           10000         USERS
P19999          20000         USERS
PMAX            MAXVALUE      USERS


--- 서브 파티션 컬럼 정보
HR@ora11g> select * from user_subpart_key_columns where name = 'EMP_COMP';

NAME                                          OBJECT_TYPE   COLUMN_NAME          COLUMN_POSITION
--------------------------------------------- ------------- -------------------- ---------------
EMP_COMP                                      TABLE         EMPLOYEE_ID                        1


--- 서브 파티션 정보
HR@ora11g> select partition_name, subpartition_name, high_value, subpartition_position
           from user_tab_subpartitions
           where table_name = 'EMP_COMP';

PARTITION_NAME  SUBPARTITION_NAME              HIGH_VALUE    SUBPARTITION_POSITION
--------------- ------------------------------ ------------- ---------------------
P19999          SYS_SUBP69                                                       1
P19999          SYS_SUBP70                                                       2
P19999          SYS_SUBP71                                                       3
P19999          SYS_SUBP72                                                       4
P4999           SYS_SUBP61                                                       1
P4999           SYS_SUBP62                                                       2
P4999           SYS_SUBP63                                                       3
P4999           SYS_SUBP64                                                       4
P9999           SYS_SUBP65                                                       1
P9999           SYS_SUBP66                                                       2
P9999           SYS_SUBP67                                                       3
P9999           SYS_SUBP68                                                       4
PMAX            SYS_SUBP73                                                       1
PMAX            SYS_SUBP74                                                       2
PMAX            SYS_SUBP75                                                       3
PMAX            SYS_SUBP76                                                       4



# Range - Hash + WHERE salary < 5000

HR@ora11g> select /*+ gather_plan_statistics */ * from hr.emp_comp where salary < 5000;


HR@ora11g> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

------------------------------------------------------------------------------------------------------
| Id  | Operation              | Name     | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  |
------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |          |      1 |        |     50 |00:00:00.01 |      16 |      1 |
|   1 |  PARTITION RANGE SINGLE|          |      1 |     49 |     50 |00:00:00.01 |      16 |      1 |
|   2 |   PARTITION HASH ALL   |          |      1 |     49 |     50 |00:00:00.01 |      16 |      1 |
|   3 |    TABLE ACCESS FULL   | EMP_COMP |      4 |     49 |     50 |00:00:00.01 |      16 |      1 |
------------------------------------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement (level=2)

> 메인 파티션 1번 검색



# Range - Hash + WHERE salary < 5000 AND employee_id = 200

HR@ora11g> select /*+ gather_plan_statistics */ * from hr.emp_comp 
           where salary < 5000 and employee_id = 200;


HR@ora11g> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

---------------------------------------------------------------------------------------------
| Id  | Operation              | Name     | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |          |      1 |        |      1 |00:00:00.01 |       4 |
|   1 |  PARTITION RANGE SINGLE|          |      1 |      1 |      1 |00:00:00.01 |       4 |
|   2 |   PARTITION HASH SINGLE|          |      1 |      1 |      1 |00:00:00.01 |       4 |
|*  3 |    TABLE ACCESS FULL   | EMP_COMP |      1 |      1 |      1 |00:00:00.01 |       4 |
---------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("EMPLOYEE_ID"=200)

Note
-----
   - dynamic sampling used for this statement (level=2)

> 메인 파티션 1개 안에 4분할 서브 파티션 다 검색

 

 

# Range - Hash + WHERE employee_id = 200

HR@ora11g> select /*+ gather_plan_statistics */ * from hr.emp_comp where employee_id = 200;


HR@ora11g> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

---------------------------------------------------------------------------------------------
| Id  | Operation              | Name     | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |          |      1 |        |      1 |00:00:00.01 |      10 |
|   1 |  PARTITION RANGE ALL   |          |      1 |      1 |      1 |00:00:00.01 |      10 |
|   2 |   PARTITION HASH SINGLE|          |      4 |      1 |      1 |00:00:00.01 |      10 |
|*  3 |    TABLE ACCESS FULL   | EMP_COMP |      4 |      1 |      1 |00:00:00.01 |      10 |
---------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("EMPLOYEE_ID"=200)

Note
-----
   - dynamic sampling used for this statement (level=2)

> 메인 파티션의 기준이 되는 salary 조건문이 없어 파티션 전체 I/O 발생




# Range - List partition

HR@ora11g> drop table hr.emp_year purge;

--- 테이블 생성
HR@ora11g> create table hr.emp_year
           partition by range(hire_date)
           subpartition by list(department_id)
           subpartition template
           (subpartition s_dept_1 values(10,20,30,40),
            subpartition s_dept_2 values(50),
            subpartition s_dept_3 values(60,70,80,90,100,110),
            subpartition s_dept_4 values(default))
           (partition p2004 values less than (to_date('2005-01-01','yyyy-mm-dd')),
            partition p2005 values less than (to_date('2006-01-01','yyyy-mm-dd')),
            partition p2006 values less than (to_date('2007-01-01','yyyy-mm-dd')),
            partition pmax values less than (maxvalue))
           as
           select employee_id, last_name, salary, hire_date, department_id from hr.employees;

Table created.


--- 테이블 내 파티션 개수
HR@ora11g> select partitioning_type, partition_count, subpartitioning_type, def_subpartition_count
           from user_part_tables where table_name = 'EMP_YEAR';

PARTITION PARTITION_COUNT SUBPARTIT DEF_SUBPARTITION_COUNT
--------- --------------- --------- ----------------------
RANGE                   4 LIST                           4


--- 주 파티션 컬럼 정보
HR@ora11g> select * from user_part_key_columns where name = 'EMP_YEAR';

NAME                                          OBJECT_TYPE   COLUMN_NAME          COLUMN_POSITION
--------------------------------------------- ------------- -------------------- ---------------
EMP_YEAR                                      TABLE         HIRE_DATE                          1


--- 주 파티션 정보
HR@ora11g> select partition_name, high_value, tablespace_name
           from user_tab_partitions
           where table_name = 'EMP_YEAR';

PARTITION_NAME  HIGH_VALUE                                                                       TABLESPACE_NAME
--------------- -------------------------------------------------------------------------------- ---------------
P2004           TO_DATE(' 2005-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA USERS
P2005           TO_DATE(' 2006-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA USERS
P2006           TO_DATE(' 2007-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA USERS
PMAX            MAXVALUE                                                                         USERS


--- 서브 파티션 컬럼 정보
HR@ora11g> select * from user_subpart_key_columns where name = 'EMP_YEAR';

NAME                                          OBJECT_TYPE   COLUMN_NAME          COLUMN_POSITION
--------------------------------------------- ------------- -------------------- ---------------
EMP_YEAR                                      TABLE         DEPARTMENT_ID                      1


--- 서브 파티션 정보
HR@ora11g> select partition_name, subpartition_name, high_value, subpartition_position
           from user_tab_subpartitions
           where table_name = 'EMP_YEAR';

PARTITION_NAME  SUBPARTITION_NAME              HIGH_VALUE                    SUBPARTITION_POSITION
--------------- ------------------------------ ----------------------------- ---------------------
P2004           P2004_S_DEPT_1                 10, 20, 30, 40                                    1
P2004           P2004_S_DEPT_2                 50                                                2
P2004           P2004_S_DEPT_3                 60, 70, 80, 90, 100, 110                          3
P2004           P2004_S_DEPT_4                 default                                           4
P2005           P2005_S_DEPT_1                 10, 20, 30, 40                                    1
P2005           P2005_S_DEPT_2                 50                                                2
P2005           P2005_S_DEPT_3                 60, 70, 80, 90, 100, 110                          3
P2005           P2005_S_DEPT_4                 default                                           4
P2006           P2006_S_DEPT_1                 10, 20, 30, 40                                    1
P2006           P2006_S_DEPT_2                 50                                                2
P2006           P2006_S_DEPT_3                 60, 70, 80, 90, 100, 110                          3
P2006           P2006_S_DEPT_4                 default                                           4
PMAX            PMAX_S_DEPT_1                  10, 20, 30, 40                                    1
PMAX            PMAX_S_DEPT_2                  50                                                2
PMAX            PMAX_S_DEPT_3                  60, 70, 80, 90, 100, 110                          3
PMAX            PMAX_S_DEPT_4                  default                                           4



# Range - List + WHERE hire_date BETWEEN ~ AND

HR@ora11g> select /*+ gather_plan_statistics */ * from hr.emp_year
           where hire_date between to_date('2002-01-01','yyyy-mm-dd')
           and to_date('2002-12-31 23:59:59','yyyy-mm-dd hh24:mi:ss');


HR@ora11g> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

---------------------------------------------------------------------------------------------
| Id  | Operation              | Name     | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |          |      1 |        |      7 |00:00:00.01 |      10 |
|   1 |  PARTITION RANGE SINGLE|          |      1 |      7 |      7 |00:00:00.01 |      10 |
|   2 |   PARTITION LIST ALL   |          |      1 |      7 |      7 |00:00:00.01 |      10 |
|*  3 |    TABLE ACCESS FULL   | EMP_YEAR |      4 |      7 |      7 |00:00:00.01 |      10 |
---------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter(("HIRE_DATE">=TO_DATE(' 2002-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND 
               "HIRE_DATE"<=TO_DATE(' 2002-12-31 23:59:59', 'syyyy-mm-dd hh24:mi:ss')))

Note
-----
   - dynamic sampling used for this statement (level=2)

> 메인 파티션의 hire_date 기준으로 검색



# Range - List + WHERE hire_date BETWEEN ~ AND + department_id

HR@ora11g> select /*+ gather_plan_statistics */ * from hr.emp_year
           where hire_date between to_date('2002-01-01','yyyy-mm-dd')
           and to_date('2002-12-31 23:59:59','yyyy-mm-dd hh24:mi:ss')
           and department_id = 30;


HR@ora11g> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

---------------------------------------------------------------------------------------------
| Id  | Operation              | Name     | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |          |      1 |        |      1 |00:00:00.01 |       4 |
|   1 |  PARTITION RANGE SINGLE|          |      1 |      1 |      1 |00:00:00.01 |       4 |
|   2 |   PARTITION LIST SINGLE|          |      1 |      1 |      1 |00:00:00.01 |       4 |
|*  3 |    TABLE ACCESS FULL   | EMP_YEAR |      1 |      1 |      1 |00:00:00.01 |       4 |
---------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter(("DEPARTMENT_ID"=30 AND "HIRE_DATE">=TO_DATE(' 2002-01-01 00:00:00',
              'syyyy-mm-dd hh24:mi:ss') AND "HIRE_DATE"<=TO_DATE(' 2002-12-31 23:59:59',
              'syyyy-mm-dd hh24:mi:ss')))

Note
-----
   - dynamic sampling used for this statement (level=2)

> 메인 파티션 기준 hire_date + 서브 파티션 기준 department_id 같이 검색

 

 

 

 

# Logging Mode 상태 확인

HR@ora11g> drop table hr.emp_year purge;

HR@ora11g> create table hr.emp_year
           partition by range(hire_date)
           subpartition by list(department_id)
           subpartition template
           (subpartition s_dept_1 values(10,20,30,40),
            subpartition s_dept_2 values(50),
            subpartition s_dept_3 values(60,70,80,90,100,110),
            subpartition s_dept_4 values(default))
           (partition p2004 values less than (to_date('2005-01-01','yyyy-mm-dd')),
            partition p2005 values less than (to_date('2006-01-01','yyyy-mm-dd')),
            partition p2006 values less than (to_date('2007-01-01','yyyy-mm-dd')),
            partition pmax values less than (maxvalue))
           nologging
           as 
           select employee_id, last_name, salary, hire_date, department_id from hr.employees;

Table created.


HR@ora11g> select partition_name, high_value, tablespace_name, logging
           from user_tab_partitions
           where table_name = 'EMP_YEAR';

PARTITION_NAME  HIGH_VALUE                                                                       TABLESPACE_NAME LOGGING
--------------- -------------------------------------------------------------------------------- --------------- -------
P2004           TO_DATE(' 2005-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA USERS           NONE
P2005           TO_DATE(' 2006-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA USERS           NONE
P2006           TO_DATE(' 2007-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA USERS           NONE
PMAX            MAXVALUE                                                                         USERS           NONE


--- Logging Mode로 전환
HR@ora11g> alter table hr.emp_year logging;

Table altered.


HR@ora11g> select partition_name, high_value, tablespace_name, logging
           from user_tab_partitions
           where table_name = 'EMP_YEAR';

PARTITION_NAME  HIGH_VALUE                                                                       TABLESPACE_NAME LOGGING
--------------- -------------------------------------------------------------------------------- --------------- -------
P2004           TO_DATE(' 2005-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA USERS           YES
P2005           TO_DATE(' 2006-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA USERS           YES
P2006           TO_DATE(' 2007-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA USERS           YES
PMAX            MAXVALUE                                                                         USERS           YES

> Logging Mode 상태를 꼭 확인하자.




# Logging Mode 상태 확인 2

HR@ora11g> create table hr.no_emp
nologging
as select * from hr.employees;

Table created.


HR@ora11g> select logging from user_tables where table_name = 'NO_EMP';

LOGGING
-------
NO


HR@ora11g> alter table hr.no_emp logging;

Table altered.


HR@ora11g> select logging from user_tables where table_name = 'NO_EMP';

LOGGING
-------
YES



HR@ora11g> drop table hr.no_emp purge;

Table dropped.





# 예시 : Partition by Range(salary)

HR@ora11g> create table hr.sal_emp
           partition by range(salary)
           (partition p1 values less than (5000),
            partition p2 values less than (15000),
            partition p3 values less than (25000))
           as select employee_id, last_name, salary, department_id from hr.employees;

Table created.


HR@ora11g> select partition_name, high_value, tablespace_name, logging
           from user_tab_partitions
           where table_name = 'SAL_EMP';

PARTITION_NAME  HIGH_VALUE     TABLESPACE_NAME LOGGING
--------------- -------------- --------------- -------
P1              5000           USERS           YES
P2              15000          USERS           YES
P3              25000          USERS           YES


HR@ora11g> select partitioning_type, partition_count 
           from user_part_tables where table_name = 'SAL_EMP';

PARTITION PARTITION_COUNT
--------- ---------------
RANGE                   3

 

 

 

# Partition 나누기 : Split

HR@ora11g> alter table sal_emp split partition p3 at(20000) into (partition p3, partition p4);

Table altered.

> p3 25000 -> p3 20000, p4 25000


HR@ora11g> select partition_name, high_value, tablespace_name
           from user_tab_partitions
           where table_name = 'SAL_EMP';

PARTITION_NAME  HIGH_VALUE     TABLESPACE_NAME
--------------- -------------- ---------------
P1              5000           USERS
P2              15000          USERS
P3              20000          USERS
P4              25000          USERS

 

 

 

# Partition 추가 : Add

HR@ora11g> alter table sal_emp add partition p5_1 values less than (30000);

Table altered.

> p5_1 (~30000) 파티션 추가


HR@ora11g> select partition_name, high_value, tablespace_name
           from user_tab_partitions
           where table_name = 'SAL_EMP';

PARTITION_NAME  HIGH_VALUE     TABLESPACE_NAME
--------------- -------------- ---------------
P1              5000           USERS
P2              15000          USERS
P3              20000          USERS
P4              25000          USERS
P5_1            30000          USERS

 

 

# Partition 이름 변경 : Rename

HR@ora11g> alter table sal_emp rename partition p5_1 to p5;

Table altered.

> p5_1 -> P5


HR@ora11g> select partition_name, high_value, tablespace_name
           from user_tab_partitions
           where table_name = 'SAL_EMP';

PARTITION_NAME  HIGH_VALUE     TABLESPACE_NAME
--------------- -------------- ---------------
P1              5000           USERS
P2              15000          USERS
P3              20000          USERS
P4              25000          USERS
P5              30000          USERS

 

 

 

# Partition 삭제 : Drop

HR@ora11g> alter table sal_emp drop partition p5;

Table altered.

> ** drop table sal_emp은 테이블 자체를 삭제하는 것이니 사용 주의


HR@ora11g> select partition_name, high_value, tablespace_name
           from user_tab_partitions
           where table_name = 'SAL_EMP';

PARTITION_NAME  HIGH_VALUE     TABLESPACE_NAME
--------------- -------------- ---------------
P1              5000           USERS
P2              15000          USERS
P3              20000          USERS
P4              25000          USERS



# Partition 내 Data 삭제: Truncate

HR@ora11g> select * from hr.sal_emp partition (p3);

2 rows selected


--- Partition Data Truncate
HR@ora11g> alter table hr.sal_emp truncate partition p3;

Table truncated.


HR@ora11g> select * from hr.sal_emp partition (p3);

no rows selected

> delete 하면 redo, undo 발생


--- 복구
HR@ora11g> insert into sal_emp select employee_id, last_name, salary, department_id 
           from employees where employee_id in (101,102);

2 rows created.

HR@ora11g> commit;

Commit complete.

HR@ora11g> select * from hr.sal_emp partition (p3);

2 rows selected

 

 

 

# 파티션 키컬럼 값 수정 : Flashback Table

HR@ora11g> update hr.sal_emp set salary = 24000 where employee_id = 100;

ORA-14402: updating partition key column would cause a partition change

> hr.sal_emp : partition by range(salary)
> p1에 있는 값을 p4에 이동이 필요한 상황 -> 키 컬럼 업데이트는 맘대로 할 수 없다.


↓ p.76 참고

--- 행 이동이 활성화
HR@ora11g> alter table hr.sal_emp enable row movement;

Table altered.


HR@ora11g> update hr.sal_emp set salary = 24000 where employee_id = 100;

1 row updated.

HR@ora11g> commit;

Commit complete.


--- 행 이동이 비활성화
HR@ora11g> alter table hr.sal_emp disable row movement;

Table altered.


HR@ora11g> select * from hr.sal_emp partition (p4);

EMPLOYEE_ID LAST_NAME                     SALARY DEPARTMENT_ID
----------- ------------------------- ---------- -------------
        100 King                           24000            90

 

 

 

# Maxvalue Partition 추가

--- Add Partition : pmax (~maxvalue)
HR@ora11g> alter table hr.sal_emp add partition pmax values less than (maxvalue);

Table altered.


HR@ora11g> select partition_name, high_value, tablespace_name
           from user_tab_partitions
           where table_name = 'SAL_EMP';

PARTITION_NAME  HIGH_VALUE     TABLESPACE_NAME
--------------- -------------- ---------------
P1              5000           USERS
P2              15000          USERS
P3              20000          USERS
P4              25000          USERS
PMAX            MAXVALUE       USERS


--- Insert Data
HR@ora11g> insert into sal_emp(employee_id,last_name,salary,department_id) 
                  values(300,'oracle',30000,10);

1 row created.

HR@ora11g> commit;

Commit complete.

HR@ora11g> select * from hr.sal_emp partition (pmax);

EMPLOYEE_ID LAST_NAME                     SALARY DEPARTMENT_ID
----------- ------------------------- ---------- -------------
        300 oracle                         30000            10


--- Split Partition
HR@ora11g> alter table hr.sal_emp 
           split partition pmax at(30000) into (partition p5, partition pmax);

Table altered.

> pmax -> p5 ~30000, pmax ~maxvalue


HR@ora11g> select partition_name, high_value, tablespace_name
           from user_tab_partitions
           where table_name = 'SAL_EMP';

PARTITION_NAME  HIGH_VALUE     TABLESPACE_NAME
--------------- -------------- ---------------
P1              5000           USERS
P2              15000          USERS
P3              20000          USERS
P4              25000          USERS
P5              30000          USERS
PMAX            MAXVALUE       USERS

 

 

# Partition Merge

HR@ora11g> select * from hr.sal_emp partition (p4);

EMPLOYEE_ID LAST_NAME                     SALARY DEPARTMENT_ID
----------- ------------------------- ---------- -------------
        100 King                           24000            90


HR@ora11g> select * from hr.sal_emp partition (p5);

no rows selected


--- Merge
HR@ora11g> alter table hr.sal_emp merge partitions p4, p5 into partition p5;

Table altered.

> p4 Data -> p5 병합


HR@ora11g> select partition_name, high_value, tablespace_name
           from user_tab_partitions
           where table_name = 'SAL_EMP';

PARTITION_NAME  HIGH_VALUE     TABLESPACE_NAME
--------------- -------------- ---------------
P1              5000           USERS
P2              15000          USERS
P3              20000          USERS
P5              30000          USERS
PMAX            MAXVALUE       USERS


HR@ora11g> select * from hr.sal_emp partition (p5);

EMPLOYEE_ID LAST_NAME                     SALARY DEPARTMENT_ID
----------- ------------------------- ---------- -------------
        100 King                           24000            90

 


# Partition Exchange (데이터 교환)

HR@ora11g> create table hr.exch_emp as select employee_id, last_name, salary, department_id
           from hr.employees where 1 = 2;

Table created.

HR@ora11g> select * from hr.exch_emp;

no rows selected


HR@ora11g> select * from hr.sal_emp partition (p5);

EMPLOYEE_ID LAST_NAME                     SALARY DEPARTMENT_ID
----------- ------------------------- ---------- -------------
        100 King                           24000            90


--- Exchange
HR@ora11g> alter table hr.sal_emp exchange partition p5 with table hr.exch_emp;

Table altered.

> 파티션 p5와 테이블 exch_emp의 Data를 교환


HR@ora11g> select * from hr.exch_emp;

EMPLOYEE_ID LAST_NAME                     SALARY DEPARTMENT_ID
----------- ------------------------- ---------- -------------
        100 King                           24000            90

HR@ora11g> select * from hr.sal_emp partition (p5);

no rows selected


--- Re Exchange
HR@ora11g> alter table hr.sal_emp exchange partition p5 with table hr.exch_emp;

Table altered.


HR@ora11g> select * from hr.exch_emp;

no rows selected

HR@ora11g> select * from hr.sal_emp partition (p5);

EMPLOYEE_ID LAST_NAME                     SALARY DEPARTMENT_ID
----------- ------------------------- ---------- -------------
        100 King                           24000            90


--- rename
HR@ora11g> alter table hr.sal_emp rename partition p5 to p4;

Table altered.


HR@ora11g> select partition_name, high_value, tablespace_name
           from user_tab_partitions
           where table_name = 'SAL_EMP';

PARTITION_NAME  HIGH_VALUE     TABLESPACE_NAME
--------------- -------------- ---------------
P1              5000           USERS
P2              15000          USERS
P3              20000          USERS
P4              30000          USERS
PMAX            MAXVALUE       USERS

 

 

# Partition Table 통계 수집  : granularity => 'auto'

--- 파티션 통계 수집
HR@ora11g> exec dbms_stats.gather_table_stats('hr','sal_emp',granularity=>'auto')

PL/SQL procedure successfully completed.


HR@ora11g> select partition_name, high_value, tablespace_name, num_rows, blocks, avg_row_len
           from user_tab_partitions
           where table_name = 'SAL_EMP';

PARTITION_NAME  HIGH_VALUE     TABLESPACE_NAME   NUM_ROWS     BLOCKS AVG_ROW_LEN
--------------- -------------- --------------- ---------- ---------- -----------
P1              5000           USERS                   49         19          17
P2              15000          USERS                   55         19          17
P3              20000          USERS                    2         46          19
P4              30000          USERS                    1         19          15
PMAX            MAXVALUE       USERS                    1         46          16


HR@ora11g> select num_rows, blocks, avg_row_len 
           from user_tables where table_name = 'SAL_EMP';

  NUM_ROWS     BLOCKS AVG_ROW_LEN
---------- ---------- -----------
       108        149          17


HR@ora11g> select * from hr.sal_emp partition (p3);

EMPLOYEE_ID LAST_NAME                     SALARY DEPARTMENT_ID
----------- ------------------------- ---------- -------------
        101 Kochhar                        17000            90
        102 De Haan                        17000            90

> 데이터 대비 사용 block이 많다 > 리오브 대상

 

 

 

 

 

# Data Pump

 

# 논리적 디렉터리 위치 확인

SYS@ora11g> select * from dba_directories;

OWNER      DIRECTORY_NAME                 DIRECTORY_PATH
---------- ------------------------------ ---------------------------------------------------------------------------
SYS        SUBDIR                         /u01/app/oracle/product/11.2.0.4/db_1/demo/schema/order_entry//2002/Sep
SYS        SS_OE_XMLDIR                   /u01/app/oracle/product/11.2.0.4/db_1/demo/schema/order_entry/
SYS        LOG_FILE_DIR                   /u01/app/oracle/product/11.2.0.4/db_1/demo/schema/log/
SYS        MEDIA_DIR                      /u01/app/oracle/product/11.2.0.4/db_1/demo/schema/product_media/
SYS        DATA_FILE_DIR                  /u01/app/oracle/product/11.2.0.4/db_1/demo/schema/sales_history/
SYS        XMLDIR                         /u01/app/oracle/product/11.2.0.4/db_1/rdbms/xml
SYS        ORACLE_OCM_CONFIG_DIR          /u01/app/oracle/product/11.2.0.4/db_1/ccr/hosts/oracle/state
SYS        DATA_PUMP_DIR                  /u01/app/oracle/admin/ora11g/dpdump/
SYS        ORACLE_OCM_CONFIG_DIR2         /u01/app/oracle/product/11.2.0.4/db_1/ccr/state

> DATA_PUMP_DIR 사용



# Expdp : 특정 Table 내보내기

[oracle@oracle ~]$ expdp system/oracle directory=data_pump_dir tables=hr.sal_emp dumpfile=hr_sal_emp.pump

Export: Release 11.2.0.4.0 - Production on Mon Feb 26 15:55:51 2024

Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Starting "SYSTEM"."SYS_EXPORT_TABLE_01":  system/******** directory=data_pump_dir tables=hr.sal_emp dumpfile=hr_sal_emp.pump
Estimate in progress using BLOCKS method...
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
Total estimation using BLOCKS method: 40 MB
Processing object type TABLE_EXPORT/TABLE/TABLE
Processing object type TABLE_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
. . exported "HR"."SAL_EMP":"P1"                         7.351 KB      49 rows
. . exported "HR"."SAL_EMP":"P2"                         7.484 KB      55 rows
. . exported "HR"."SAL_EMP":"P3"                         6.390 KB       2 rows
. . exported "HR"."SAL_EMP":"P4"                         6.367 KB       1 rows
. . exported "HR"."SAL_EMP":"PMAX"                       6.367 KB       1 rows
Master table "SYSTEM"."SYS_EXPORT_TABLE_01" successfully loaded/unloaded
******************************************************************************
Dump file set for SYSTEM.SYS_EXPORT_TABLE_01 is:
  /u01/app/oracle/admin/ora11g/dpdump/hr_sal_emp.pump
Job "SYSTEM"."SYS_EXPORT_TABLE_01" successfully completed at Mon Feb 26 15:56:04 2024 elapsed 0 00:00:07

*/

 

 

 

# Drop Table

SYS@ora11g> drop table hr.sal_emp purge;

Table dropped.

 


# Impdp : 특정 테이블 가져오기

[oracle@oracle ~]$ impdp system/oracle directory=data_pump_dir tables=hr.sal_emp dumpfile=hr_sal_emp.pump

Import: Release 11.2.0.4.0 - Production on Mon Feb 26 16:00:36 2024

Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Master table "SYSTEM"."SYS_IMPORT_TABLE_01" successfully loaded/unloaded
Starting "SYSTEM"."SYS_IMPORT_TABLE_01":  system/******** directory=data_pump_dir tables=hr.sal_emp dumpfile=hr_sal_emp.pump
Processing object type TABLE_EXPORT/TABLE/TABLE
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
. . imported "HR"."SAL_EMP":"P1"                         7.351 KB      49 rows
. . imported "HR"."SAL_EMP":"P2"                         7.484 KB      55 rows
. . imported "HR"."SAL_EMP":"P3"                         6.390 KB       2 rows
. . imported "HR"."SAL_EMP":"P4"                         6.367 KB       1 rows
. . imported "HR"."SAL_EMP":"PMAX"                       6.367 KB       1 rows
Processing object type TABLE_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
Job "SYSTEM"."SYS_IMPORT_TABLE_01" successfully completed at Mon Feb 26 16:00:38 2024 elapsed 0 00:00:02

*/

[oracle@oracle ~]$ exit

SYS@ora11g> select partition_name, high_value, tablespace_name, num_rows, blocks, avg_row_len
           from dba_tab_partitions
           where table_name = 'SAL_EMP';

PARTITION_NAME  HIGH_VALUE     TABLESPACE_NAME   NUM_ROWS     BLOCKS AVG_ROW_LEN
--------------- -------------- --------------- ---------- ---------- -----------
P1              5000           USERS                   49         19          17
P2              15000          USERS                   55         19          17
P3              20000          USERS                    2         46          19
P4              30000          USERS                    1         19          15
PMAX            MAXVALUE       USERS                    1         46          16


SYS@ora11g> select * from hr.sal_emp partition (p4);

EMPLOYEE_ID LAST_NAME                     SALARY DEPARTMENT_ID
----------- ------------------------- ---------- -------------
        100 King                           24000            90

 

 

 

# p4 파티션 삭

SYS@ora11g> alter table hr.sal_emp drop partition p4;

Table altered.


# Impdp : 특정 Table을 SQL문으로 가져오

[oracle@oracle ~]$ impdp system/oracle directory=data_pump_dir dumpfile=hr_sal_emp.pump sqlfile=sql_emp.sql

Import: Release 11.2.0.4.0 - Production on Mon Feb 26 16:04:59 2024

Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Master table "SYSTEM"."SYS_SQL_FILE_FULL_01" successfully loaded/unloaded
Starting "SYSTEM"."SYS_SQL_FILE_FULL_01":  system/******** directory=data_pump_dir dumpfile=hr_sal_emp.pump sqlfile=sql_emp.sql
Processing object type TABLE_EXPORT/TABLE/TABLE
Processing object type TABLE_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
Job "SYSTEM"."SYS_SQL_FILE_FULL_01" successfully completed at Mon Feb 26 16:05:00 2024 elapsed 0 00:00:00
*/

[oracle@oracle ~]$ vi /u01/app/oracle/admin/ora11g/dpdump/sql_emp.sql

> @ sql_emp.sql 실행하면 데이터 생성 가능

 

 

 

# Impdp : 테이블 내 특정 파티션의 데이터만 가져오기

--- 삭제한 파티션 p4 생성 : split 이용
SYS@ora11g> alter table hr.sal_emp 
            split partition pmax at (30000) into (partition p4, partition pmax);

Table altered.

> p4가 삭제된 상태
> pmax -> p4 ~3000, pmax ~maxvalue


SYS@ora11g> select * from hr.sal_emp partition (p4);

no rows selected


--- 테이블의 p4 파티션의 데이터만 가져오기
[oracle@oracle ~]$ impdp system/oracle directory=data_pump_dir dumpfile=hr_sal_emp.pump tables=hr.sal_emp:p4 content=data_only

Import: Release 11.2.0.4.0 - Production on Mon Feb 26 16:12:04 2024

Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Master table "SYSTEM"."SYS_IMPORT_TABLE_01" successfully loaded/unloaded
Starting "SYSTEM"."SYS_IMPORT_TABLE_01":  system/******** directory=data_pump_dir dumpfile=hr_sal_emp.pump tables=hr.sal_emp:p4 content=data_only
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
. . imported "HR"."SAL_EMP":"P4"                         6.367 KB       1 rows
Job "SYSTEM"."SYS_IMPORT_TABLE_01" successfully completed at Mon Feb 26 16:12:06 2024 elapsed 0 00:00:02
*/

[oracle@oracle ~]$ exit

SYS@ora11g> select * from hr.sal_emp partition (p4);

EMPLOYEE_ID LAST_NAME                     SALARY DEPARTMENT_ID
----------- ------------------------- ---------- -------------
        100 King                           24000            90

 


# p3 데이터만 삭제
SYS@ora11g> alter table hr.sal_emp truncate partition p3;

Table truncated.

SYS@ora11g> select * from hr.sal_emp partition (p3);

no rows selected

 

# Impdp : 테이블 내 특정 파티션의 데이터만 가져오기

[oracle@oracle ~]$ impdp system/oracle directory=data_pump_dir dumpfile=hr_sal_emp.pump tables=hr.sal_emp:p3 content=data_only

Import: Release 11.2.0.4.0 - Production on Mon Feb 26 16:14:36 2024

Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Master table "SYSTEM"."SYS_IMPORT_TABLE_01" successfully loaded/unloaded
Starting "SYSTEM"."SYS_IMPORT_TABLE_01":  system/******** directory=data_pump_dir dumpfile=hr_sal_emp.pump tables=hr.sal_emp:p3 content=data_only
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
. . imported "HR"."SAL_EMP":"P3"                         6.390 KB       2 rows
Job "SYSTEM"."SYS_IMPORT_TABLE_01" successfully completed at Mon Feb 26 16:14:37 2024 elapsed 0 00:00:01

 

 

 

# 특정 Partition 통계 수집 : granularity => 'partition'

SYS@ora11g> select * from hr.sal_emp partition (p3);

EMPLOYEE_ID LAST_NAME                     SALARY DEPARTMENT_ID
----------- ------------------------- ---------- -------------
        101 Kochhar                        17000            90
        102 De Haan                        17000            90


SYS@ora11g> select partition_name, high_value, tablespace_name, num_rows, blocks, avg_row_len
           from dba_tab_partitions
           where table_name = 'SAL_EMP';

PARTITION_NAME  HIGH_VALUE     TABLESPACE_NAME   NUM_ROWS     BLOCKS AVG_ROW_LEN
--------------- -------------- --------------- ---------- ---------- -----------
P1              5000           USERS                   49         19          17
P2              15000          USERS                   55         19          17
P3              20000          USERS                    2         46          19
P4              30000          USERS
PMAX            MAXVALUE       USERS                    1         46          16


--- p4 파티션만 통계 수집
SYS@ora11g> exec dbms_stats.gather_table_stats('hr', 'sal_emp', partname => 'p4', granularity=>'partition')

PL/SQL procedure successfully completed.


SYS@ora11g> select partition_name, high_value, tablespace_name, num_rows, blocks, avg_row_len
           from dba_tab_partitions
           where table_name = 'SAL_EMP';

PARTITION_NAME  HIGH_VALUE     TABLESPACE_NAME   NUM_ROWS     BLOCKS AVG_ROW_LEN
--------------- -------------- --------------- ---------- ---------- -----------
P1              5000           USERS                   49         19          17
P2              15000          USERS                   55         19          17
P3              20000          USERS                    2         46          19
P4              30000          USERS                    1         19          15
PMAX            MAXVALUE       USERS                    1         46          16



# 특정 Partition만 Export

[oracle@oracle ~]$ expdp system/oracle directory=data_pump_dir tables=hr.sal_emp:p4 dumpfile=hr_sal_emp_p4.pump

Export: Release 11.2.0.4.0 - Production on Mon Feb 26 16:22:51 2024

Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Starting "SYSTEM"."SYS_EXPORT_TABLE_01":  system/******** directory=data_pump_dir tables=hr.sal_emp:p4 dumpfile=hr_sal_emp_p4.pump
Estimate in progress using BLOCKS method...
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
Total estimation using BLOCKS method: 8 MB
Processing object type TABLE_EXPORT/TABLE/TABLE
Processing object type TABLE_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
. . exported "HR"."SAL_EMP":"P4"                         6.367 KB       1 rows
Master table "SYSTEM"."SYS_EXPORT_TABLE_01" successfully loaded/unloaded
******************************************************************************
Dump file set for SYSTEM.SYS_EXPORT_TABLE_01 is:
  /u01/app/oracle/admin/ora11g/dpdump/hr_sal_emp_p4.pump
Job "SYSTEM"."SYS_EXPORT_TABLE_01" successfully completed at Mon Feb 26 16:22:54 2024 elapsed 0 00:00:03

 

 

# 특정 파티션 Data 삭제 : Truncate
SYS@ora11g> alter table hr.sal_emp truncate partition p4;

Table truncated.

 

 

# Impdp : 특정 파티션의 데이터만 가져오기

[oracle@oracle ~]$ impdp system/oracle directory=data_pump_dir dumpfile=hr_sal_emp_p4.pump tables=hr.sal_emp:p4 content=data_only

Import: Release 11.2.0.4.0 - Production on Mon Feb 26 16:26:36 2024

Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Master table "SYSTEM"."SYS_IMPORT_TABLE_01" successfully loaded/unloaded
Starting "SYSTEM"."SYS_IMPORT_TABLE_01":  system/******** directory=data_pump_dir dumpfile=hr_sal_emp_p4.pump tables=hr.sal_emp content=data_only
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
. . imported "HR"."SAL_EMP":"P4"                         6.367 KB       1 rows
Job "SYSTEM"."SYS_IMPORT_TABLE_01" successfully completed at Mon Feb 26 16:26:38 2024 elapsed 0 00:00:01
*/

[oracle@oracle ~]$ exit

SYS@ora11g> select * from hr.sal_emp partition (p4);

EMPLOYEE_ID LAST_NAME                     SALARY DEPARTMENT_ID
----------- ------------------------- ---------- -------------
        100 King                           24000            90

> 애당초 원본 hr_sal_emp_p4.pump 파일안에 파티션 p4 데이터만 있어 
  그냥 tables=hr.sal_emp 테이블만 표기해도 무관하다.

 

'Oracle 11g > Tuning' 카테고리의 다른 글

94 Parallel  (3) 2024.02.28
93 Arraysize, Partition Pruning, Local/Global Partitioned Indexes  (1) 2024.02.27
91 통계정보  (0) 2024.02.23
90 Pushdown, Pullup, Use_concat, Optimazer  (0) 2024.02.22
89 Pushing Subquery, View Merging, Pushdown  (0) 2024.02.21