h1.1. Partition online move
SQL> create table part_move_test (
name varchar2(10),
dob date
)
partition by range (dob)
interval (numtodsinterval(7, 'DAY'))
(partition p_jan1971 values less than (to_DatE('19710101','yyyymmdd'))
);
Statement Processed.
SQL> insert into part_move_test values ('name1',to_Date('2016/12/01','yyyy/mm/dd'));
1 rows Inserted.
SQL> insert into part_move_test values ('name2',to_Date('2016/12/02','yyyy/mm/dd'));
1 rows Inserted.
SQL> insert into part_move_test values ('name3',to_Date('2016/12/03','yyyy/mm/dd'));
1 rows Inserted.
SQL> insert into part_move_test values ('name4',to_Date('2016/12/04','yyyy/mm/dd'));
1 rows Inserted.
SQL> SELECT table_name, partition_name, num_rows, tablespace_name
FROM USER_TAB_PARTITIONS WHERE TABLE_NAME='PART_MOVE_TEST';
TABLE_NAME PARTITION_NAME NUM_ROWS TABLESPACE_NAME
------------------------------ ------------------------------ ---------- ------------------------------
PART_MOVE_TEST P_JAN1971 0 USERS
PART_MOVE_TEST SYS_P426 1 USERS
PART_MOVE_TEST SYS_P427 3 USERS
SQL> alter table part_move_test move partition SYS_P426 tablespace ts_1 online ;
Table altered.
SQL> SELECT table_name, partition_name, num_rows, tablespace_name
FROM USER_TAB_PARTITIONS WHERE TABLE_NAME='PART_MOVE_TEST'
TABLE_NAME PARTITION_NAME NUM_ROWS TABLESPACE_NAME
------------------------------ ------------------------------ ---------- ------------------------------
PART_MOVE_TEST P_JAN1971 0 USERS
PART_MOVE_TEST SYS_P426 1 TS_1
PART_MOVE_TEST SYS_P427 3 USERS
SQL>
SQL> create table move_test (name varchar2(30), dob date ) tablespace users;
Table created.
SQL> insert into move_test select object_name, created from dba_objects;
90794 rows created.
SQL>
SQL> commit;
Commit complete.
SQL> alter table move_test move tablespace ts_1 online ;
alter table move_test move tablespace ts_1 online
*
ERROR at line 1:
ORA-01735: invalid ALTER TABLE option
h1.2. Interval-Reference Partition
SQL> create table orders (
order_id number
,name varchar2(30)
,order_date date
)
partition by range (order_date)
(
partition p_1 values less than (to_date('2015/01/01','yyyy/mm/dd')),
partition p_2 values less than (to_date('2016/01/01','yyyy/mm/dd')),
partition p_3 values less than (to_date('2017/01/01','yyyy/mm/dd'))
);
Statement Processed.
SQL> alter table orders add constraint pk_orders primary key (order_id);
Statement Processed.
SQL> create table order_items (
order_id number not null
,product_id number
,sales_cmount number
,constraint order_items_fk foreign key (order_id) references orders (order_id) on delete cascade
)
partition by reference (order_items_fk);
Statement Processed.
SQL> insert into orders select object_id, object_name, created from dba_objects;
90816 rows Inserted.
SQL> commit;
Commit complete.
SQL> insert into order_items select object_id, namespace, data_object_id from dba_objects;
90812 rows Inserted.
SQL> commit;
Commit complete.
SQL> exec dbms_stats.gather_Table_stats('TESTUSER','ORDERS')
PL/SQL executed.
SQL> exec dbms_stats.gather_Table_stats('TESTUSER','ORDER_ITEMS')
PL/SQL executed.
SQL> select table_name, partition_name, high_value, num_rows
from user_tab_partitions where table_name in ('ORDERS','ORDER_ITEMS');
TABLE_NAME PARTITION_NAME HIGH_VALUE NUM_ROWS
------------------------------ ------------------------------ -------------------------------------------------------------------------------- ----------
ORDER_ITEMS P_3 50
ORDER_ITEMS P_2 9
ORDER_ITEMS P_1 90753
ORDERS P_3 TO_DATE(' 2017-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA 54
ORDERS P_2 TO_DATE(' 2016-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA 9
ORDERS P_1 TO_DATE(' 2015-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA 90753
6 rows selected.
SQL>
SQL> SELECT
TABLE_NAME, PARTITIONING_TYPE, REF_PTN_CONSTRAINT_NAME, INTERVAL
FROM USER_PART_TABLES
WHERE TABLE_NAME IN ('ORDERS','ORDER_ITEMS')
;
TABLE_NAME PARTITION REF_PTN_CONSTRAINT_NAME INTERVAL
------------------------------ --------- ------------------------------ --------------------------------------------------
ORDERS RANGE
ORDER_ITEMS REFERENCE ORDER_ITEMS_FK
SQL>
SQL> create table orders (
order_id number
,name varchar2(30)
,order_date date
)
partition by range (order_date) interval (numtodsinterval(7,'DAY'))
(partition p_1 values less than (to_date('2015/01/01','yyyy/mm/dd'))
);
Statement Processed.
SQL> alter table orders add constraint pk_orders primary key (order_id);
Statement Processed.
SQL> create table order_items (
order_id number not null
,product_id number
,sales_cmount number
,constraint order_items_fk foreign key (order_id) references orders (order_id) on delete cascade
)
partition by reference (order_items_fk);
Statement Processed.
SQL> insert into orders select object_id, object_name, created from dba_objects where owner != 'TESTUSER';
90793 rows Inserted.
SQL> commit;
Commit complete.
SQL> insert into order_items select object_id, namespace, data_object_id from dba_objects where owner != 'TESTUSER';
90793 rows Inserted.
SQL> commit;
Commit complete.
SQL> exec dbms_stats.gather_Table_stats('TESTUSER','ORDERS')
PL/SQL executed.
SQL> exec dbms_stats.gather_Table_stats('TESTUSER','ORDER_ITEMS')
PL/SQL executed.
SQL> select
table_name, partition_name, high_value, num_rows
from user_tab_partitions where table_name in ('ORDERS','ORDER_ITEMS'); 2 3
TABLE_NAME PARTITION_NAME HIGH_VALUE NUM_ROWS
------------------------------ ------------------------------ -------------------------------------------------------------------------------- ----------
ORDER_ITEMS SYS_P523 14
ORDER_ITEMS SYS_P522 9
ORDER_ITEMS SYS_P521 17
ORDER_ITEMS P_1 90753
ORDERS SYS_P523 TO_DATE(' 2016-06-09 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA 14
ORDERS SYS_P522 TO_DATE(' 2015-04-02 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA 9
ORDERS SYS_P521 TO_DATE(' 2016-12-15 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA 17
ORDERS P_1 TO_DATE(' 2015-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA 90753
8 rows selected.
SQL> SELECT
TABLE_NAME, PARTITIONING_TYPE, REF_PTN_CONSTRAINT_NAME, INTERVAL
FROM USER_PART_TABLES
WHERE TABLE_NAME IN ('ORDERS','ORDER_ITEMS')
;
TABLE_NAME PARTITION REF_PTN_CONSTRAINT_NAME INTERVAL
------------------------------ --------- ------------------------------ --------------------------------------------------
ORDERS RANGE NUMTODSINTERVAL(7,'DAY')
ORDER_ITEMS REFERENCE ORDER_ITEMS_FK YES
SQL>
SQL> create table order_items (
order_id number not null
,product_id number
,sales_cmount number
,constraint order_items_fk foreign key (order_id) references orders (order_id) on delete cascade
)
partition by reference (order_items_fk)
;
ORA-14659: Partitioning method of the parent table is not supported
h1.3. Cascade 기능
h3.Truncate partition 의 개선
*reference partition 사용 시 truncate partition 명령어와 exchange partition 의 옵션으로 쓰일 수 있음
SQL> select count(*) from orders partition (p_1);
COUNT(*)
-----------
90753
1 rows selected.
SQL> select count(*) from order_items partition (p_1);
COUNT(*)
-----------
90753
1 rows selected.
SQL> alter table orders truncate partition (p_1) cascade;
Statement Processed.
SQL> select count(*) from orders partition (p_1);
COUNT(*)
-----------
0
1 rows selected.
SQL> select count(*) from order_items partition (p_1);
COUNT(*)
-----------
0
1 rows selected.
SQL> select count(*) from orders partition (p_1);
COUNT(*)
-----------
66187
1 rows selected.
SQL> select count(*) from order_items partition (p_1);
COUNT(*)
-----------
66187
1 rows selected.
SQL> alter table orders truncate partition (p_1) cascade
ORA-14054: invalid ALTER TABLE TRUNCATE PARTITION option
SQL> alter table orders truncate partition (p_1) cascade
ORA-14705: unique or primary keys referenced by enabled foreign keys in table "TESTUSER"."ORDER_ITEMS"
h1.4. 복수 개 파티션의 유지 보수
SQL> alter table orders add
partition p_4 values less than (to_Date('2018/01/01','yyyy/mm/dd')),
partition p_5 values less than (to_Date('2019/01/01','yyyy/mm/dd'));
Statement Processed.
SQL> alter table orders split partition p_1 into (
partition p_1_1 values less than (to_date('2013/01/01','yyyy/mm/dd')),
partition p_1_2 values less than (to_date('2014/01/01','yyyy/mm/dd')),
partition p_1_3 );
Statement Processed.
SQL> select
table_name, partition_name, high_value, num_rows
from user_tab_partitions where table_name in ('ORDERS'); 2 3
TABLE_NAME PARTITION_NAME HIGH_VALUE NUM_ROWS
------------------------------ ------------------------------ -------------------------------------------------------------------------------- ----------
ORDERS P_1_1 TO_DATE(' 2013-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
ORDERS P_1_2 TO_DATE(' 2014-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
ORDERS P_1_3 TO_DATE(' 2015-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
ORDERS P_2 TO_DATE(' 2016-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA 9
ORDERS P_3 TO_DATE(' 2017-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA 55
ORDERS P_4 TO_DATE(' 2018-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
ORDERS P_5 TO_DATE(' 2019-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
7 rows selected.
SQL> alter table orders add
partition p_4 values less than (to_Date('2018/01/01','yyyy/mm/dd')),
partition p_5 values less than (to_Date('2019/01/01','yyyy/mm/dd'))
ORA-14043: only one partition may be added
SQL> alter table orders split partition p_1 into (
partition p_1_1 values less than (to_date('2013/01/01','yyyy/mm/dd')),
partition p_1_2 values less than (to_date('2014/01/01','yyyy/mm/dd')),
partition p_1_3 )
ORA-14028: missing AT or VALUES keyword
SQL> alter table orders add
partition p_4 values less than (to_Date('2018/01/01','yyyy/mm/dd'));
Statement Processed.
SQL> alter table orders add
partition p_5 values less than (to_Date('2019/01/01','yyyy/mm/dd'));
Statement Processed.
SQL> alter table orders split partition p_1 at (to_date('2013/01/01','yyyy/mm/dd')) into (
partition p_1_1,
partition p_1_2
);
Statement Processed.
SQL> alter table orders split partition p_1_2 at (to_date('2014/01/01','yyyy/mm/dd')) into (
partition p_1_2,
partition p_1_3
);
Statement Processed.
SQL> select
table_name, partition_name, high_value, num_rows
from user_tab_partitions where table_name in ('ORDERS');
TABLE_NAME PARTITION_NAME HIGH_VALUE NUM_ROWS
------------------------------ ------------------------------ -------------------------------------------------------------------------------- ----------
ORDERS P_1_1 TO_DATE(' 2013-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA 66187
ORDERS P_1_2 TO_DATE(' 2014-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
ORDERS P_1_3 TO_DATE(' 2015-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
ORDERS P_2 TO_DATE(' 2016-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA 12
ORDERS P_3 TO_DATE(' 2017-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA 20208
ORDERS P_4 TO_DATE(' 2018-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
ORDERS P_5 TO_DATE(' 2019-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
7 rows selected.
SQL>
SQL> alter table orders merge partitions p_1_1, p_1_2, p_1_3 into partition p_1;
Statement Processed.
SQL> /
TABLE_NAME PARTITION_NAME HIGH_VALUE NUM_ROWS
------------------------------ ------------------------------ -------------------------------------------------------------------------------- ----------
ORDERS P_5 TO_DATE(' 2019-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
ORDERS P_4 TO_DATE(' 2018-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
ORDERS P_3 TO_DATE(' 2017-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA 55
ORDERS P_2 TO_DATE(' 2016-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA 9
ORDERS P_1 TO_DATE(' 2015-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SQL>
*Full indexing
모든 파티션에 인덱스가 생성
*Partial indexing
지정 된 파티션에는 인덱스가 생성 혹은 생성되지 않게 지정 가능함
인덱스 사용 공간 절약 가능
유지 보수 작업을 빠르게 할 수 있음 ex> 인덱싱 되지 않은 글로벌 파티션의 리빌드 등
create table orders (
order_id number
,name varchar2(30)
,order_date date
)
indexing off ---(1)
partition by range (order_date)
(
partition p_1 values less than (to_date('2015/01/01','yyyy/mm/dd')) indexing off, ---(2)
partition p_2 values less than (to_date('2016/01/01','yyyy/mm/dd')) indexing on, ---(3)
partition p_3 values less than (to_date('2017/01/01','yyyy/mm/dd')) ---(4)
)
;
alter table orders modify partition p_1 indexing on; ---(5)
alter table orders modify partition p_1 indexing off;
SQL> select
table_name, partition_name, indexing
from user_tab_partitions where table_name='ORDERS'
;
TABLE_NAME PARTITION_NAME INDE
------------------------------ ------------------------------ ----
ORDERS P_1 OFF
ORDERS P_2 ON
ORDERS P_3 OFF
SQL> create index ind1_orders_full on orders(order_date, order_id, name) global indexing full;
Index created.
SQL> SELECT INDEX_NAME, TABLE_NAME, INDEXING FROM USER_INDEXES WHERE INDEX_NAME='IND1_ORDERS_FULL';
INDEX_NAME TABLE_NAME INDEXING
------------------------------ ------------------------------ --------
IND1_ORDERS_FULL ORDERS FULL
SQL>
SQL> select bytes from dba_Segments where segment_name='IND1_ORDERS_FULL';
BYTES
----------
284164096
SQL> SELECT INDEX_NAME, TABLE_NAME, INDEXING, NUM_ROWS FROM USER_INDEXES WHERE INDEX_NAME='IND1_ORDERS_FULL';
INDEX_NAME TABLE_NAME INDEXIN NUM_ROWS
------------------------------ ------------------------------ ------- ----------
IND1_ORDERS_FULL ORDERS FULL 4540569
SQL> create index ind1_orders_partial on orders(order_id, name, order_date) global indexing partial;
Index created.
SQL> SELECT INDEX_NAME, TABLE_NAME, INDEXING FROM USER_INDEXES WHERE INDEX_NAME='IND1_ORDERS_PARTIAL';
INDEX_NAME TABLE_NAME INDEXING
------------------------------ ------------------------------ --------
IND1_ORDERS_PARTIAL ORDERS PARTIAL
SQL> select bytes from dba_Segments where segment_name='IND1_ORDERS_PARTIAL';
BYTES
----------
65536
SQL> SELECT INDEX_NAME, TABLE_NAME, INDEXING, NUM_ROWS FROM USER_INDEXES WHERE INDEX_NAME='IND1_ORDERS_PARTIAL';
INDEX_NAME TABLE_NAME INDEXIN NUM_ROWS
------------------------------ ------------------------------ ------- ----------
IND1_ORDERS_PARTIAL ORDERS PARTIAL 450
SQL>
SQL> create index ind2_orders_full on orders(order_date, name) local indexing full;
Index created.
SQL> select segment_name, partition_name, bytes from dba_Segments where segment_name='IND2_ORDERS_FULL';
SEGMENT_NAME PARTITION_NAME BYTES
------------------------------ ------------------------------ ----------
IND2_ORDERS_FULL P_3 196608
IND2_ORDERS_FULL P_2 65536
IND2_ORDERS_FULL P_1 234881024
SQL>
SQL> SELECT INDEX_NAME, TABLE_NAME, INDEXING, GLOBAL_STATS, NUM_ROWS FROM USER_INDEXES WHERE INDEX_NAME='IND2_ORDERS_FULL';
INDEX_NAME TABLE_NAME INDEXIN GLO NUM_ROWS
------------------------------ ------------------------------ ------- --- ----------
IND2_ORDERS_FULL ORDERS FULL NO 4540569
SQL> select INDEX_NAME, PARTITION_NAME, NUM_ROWS from user_ind_partitions where index_name='IND2_ORDERS_FULL';
INDEX_NAME PARTITION_NAME NUM_ROWS
------------------------------ ------------------------------ ----------
IND2_ORDERS_FULL P_1 4537650
IND2_ORDERS_FULL P_2 450
IND2_ORDERS_FULL P_3 2469
SQL> create index ind2_orders_partial on orders(order_date, name) local indexing partial;
Index created.
SQL> select segment_name, partition_name, bytes from dba_Segments where segment_name='IND2_ORDERS_PARTIAL';
SEGMENT_NAME PARTITION_NAME BYTES
------------------------------ ------------------------------ ----------
IND2_ORDERS_PARTIAL P_2 65536
SQL> SELECT INDEX_NAME, TABLE_NAME, INDEXING, GLOBAL_STATS, NUM_ROWS FROM USER_INDEXES WHERE INDEX_NAME='IND2_ORDERS_PARTIAL';
INDEX_NAME TABLE_NAME INDEXIN GLO NUM_ROWS
------------------------------ ------------------------------ ------- --- ----------
IND2_ORDERS_PARTIAL ORDERS PARTIAL NO 450
SQL> select INDEX_NAME, PARTITION_NAME, NUM_ROWS, STATUS, SEGMENT_CREATED from user_ind_partitions where index_name='IND2_ORDERS_PARTIAL';
INDEX_NAME PARTITION_NAME NUM_ROWS STATUS SEG
------------------------------ ------------------------------ ---------- -------- ---
IND2_ORDERS_PARTIAL P_1 0 UNUSABLE NO
IND2_ORDERS_PARTIAL P_2 450 USABLE YES
IND2_ORDERS_PARTIAL P_3 0 UNUSABLE NO
SQL> alter index ind1_orders_partial rebuild ;
Index altered.
SQL> SELECT INDEX_NAME, TABLE_NAME, INDEXING, NUM_ROWS FROM USER_INDEXES WHERE INDEX_NAME='IND1_ORDERS_PARTIAL';
INDEX_NAME TABLE_NAME INDEXIN NUM_ROWS
------------------------------ ------------------------------ ------- ----------
IND1_ORDERS_PARTIAL ORDERS PARTIAL 450
SQL> alter table orders modify partition p_3 indexing on ;
Table altered.
SQL> SELECT INDEX_NAME, TABLE_NAME, INDEXING, NUM_ROWS, STATUS FROM USER_INDEXES WHERE INDEX_NAME='IND1_ORDERS_PARTIAL';
INDEX_NAME TABLE_NAME INDEXIN NUM_ROWS STATUS
------------------------------ ------------------------------ ------- ---------- --------
IND1_ORDERS_PARTIAL ORDERS PARTIAL 450 VALID
SQL> alter index IND1_ORDERS_PARTIAL rebuild ;
Index altered.
SQL> SELECT INDEX_NAME, TABLE_NAME, INDEXING, NUM_ROWS, STATUS FROM USER_INDEXES WHERE INDEX_NAME='IND1_ORDERS_PARTIAL';
INDEX_NAME TABLE_NAME INDEXIN NUM_ROWS STATUS
------------------------------ ------------------------------ ------- ---------- --------
IND1_ORDERS_PARTIAL ORDERS PARTIAL 2919 VALID
SQL>
-- 생성되지 않은 partitial index 에 rebuild 시에는?
SQL> alter index IND2_ORDERS_PARTIAL rebuild partition p_1 ;
Index altered.
SQL> select INDEX_NAME, PARTITION_NAME, NUM_ROWS, STATUS, SEGMENT_CREATED from user_ind_partitions where index_name='IND2_ORDERS_PARTIAL';
INDEX_NAME PARTITION_NAME NUM_ROWS STATUS SEG
------------------------------ ------------------------------ ---------- -------- ---
IND2_ORDERS_PARTIAL P_1 4537650 USABLE YES
IND2_ORDERS_PARTIAL P_2 450 USABLE YES
IND2_ORDERS_PARTIAL P_3 0 UNUSABLE NO
SQL>
-- indexing 되지 않은 partition 에 altering 시에는?
SQL> alter table orders modify partition p_3 indexing on ;
Table altered.
SQL>
SQL> select INDEX_NAME, PARTITION_NAME, NUM_ROWS, STATUS, SEGMENT_CREATED from user_ind_partitions where index_name='IND2_ORDERS_PARTIAL';
INDEX_NAME PARTITION_NAME NUM_ROWS STATUS SEG
------------------------------ ------------------------------ ---------- -------- ---
IND2_ORDERS_PARTIAL P_1 4537650 USABLE YES
IND2_ORDERS_PARTIAL P_2 450 USABLE YES
IND2_ORDERS_PARTIAL P_3 2469 USABLE YES
SQL>
-- 이 때 table partition 속성은?
SQL> select
table_name, partition_name, indexing
from user_tab_partitions where table_name='ORDERS'
;
TABLE_NAME PARTITION_NAME INDE
------------------------------ ------------------------------ ----
ORDERS P_1 OFF -- local index rebuild
ORDERS P_2 ON
ORDERS P_3 ON -- partition indexing on
SQL>