With Oracle 12.2 and higher versions, it is really simple to convert a non-partitioned table to a partitioned table: you can now use the "ALTER TABLE .... MODIFY" syntax.
Below I am showing how I used this feature for one of my tables.
First, find some basic info about the table as it is right now:
Output:
Alter the table. I am taking the opportunity to compress the table at the same time as I am getting it partitioned. I am also using the ONLINE keyword, allowing DML against the table during the operation:
Analyze the table:
Check the table properties again:
Output:
How about compression?
Check the DBA_TAB_PARTITIONS (I am only showing the first 5 rows for brevity):
Output:
How about existing indexes?
By default, existing non-unique indexes are also partitioned during the alteration of the table.
There are two indexes on my table, one unique index supporting the primary key constraint, and one non-unique index.
Before the table was altered, both were unpartitioned:
After the table was partitioned, the non-unique index was automatically partitioned, too:
Update 18.03.2020:
Another example using LIST partitioning:
Update 12.03.2021:
An example using subpartitions:
Note that UPDATE INDEXES converts IDX_1 and IDX_2 and convert them to LOCAL indexes, on the fly.
Source: Oracle Documentation
I also recommend to look at Oracle-base.com for further reading.
First, find some basic info about the table as it is right now:
SELECT TABLE_NAME, PARTITIONED,NUM_ROWS,COMPRESSION FROM DBA_TABLES WHERE TABLE_NAME='SEGMENT_SIZE_SAMPLES';
Output:
| TABLE_NAME | PARTITIONED | NUM_ROWS | COMPRESSION |
|---|---|---|---|
| SEGMENT_SIZE_SAMPLES | NO | 948401 | DISABLED |
Alter the table. I am taking the opportunity to compress the table at the same time as I am getting it partitioned. I am also using the ONLINE keyword, allowing DML against the table during the operation:
ALTER TABLE SEGMENT_SIZE_SAMPLES MODIFY
PARTITION BY RANGE (SAMPLE_DATE)
INTERVAL
(
NUMTOYMINTERVAL(1,'MONTH')
)
(
PARTITION P_INIT VALUES LESS THAN (TO_DATE('2014-01','YYYY-MM') )
)
ROW STORE COMPRESS ADVANCED
ONLINE;
Analyze the table:
exec DBMS_STATS.GATHER_TABLE_STATS (OwnName => 'DBDRIFT',TabName => 'SEGMENT_SIZE_SAMPLES');
Check the table properties again:
SELECT TABLE_NAME, PARTITIONED,NUM_ROWS,COMPRESSION FROM DBA_TABLES WHERE TABLE_NAME='SEGMENT_SIZE_SAMPLES';
Output:
| TABLE_NAME | PARTITIONED | NUM_ROWS | COMPRESSION |
|---|---|---|---|
| SEGMENT_SIZE_SAMPLES | YES | 1000719 |
How about compression?
Check the DBA_TAB_PARTITIONS (I am only showing the first 5 rows for brevity):
SELECT TABLE_NAME, PARTITION_NAME,NUM_ROWS,COMPRESSION, COMPRESS_FOR FROM DBA_TAB_PARTITIONS WHERE TABLE_NAME='SEGMENT_SIZE_SAMPLES' FETCH FIRST 5 ROWS ONLY;
Output:
| TABLE_NAME | PARTITION_NAME | NUM_ROWS | COMPRESSION | COMPRESS_FOR |
|---|---|---|---|---|
| SEGMENT_SIZE_SAMPLES | P_INIT | 0 | ENABLED | ADVANCED |
| SEGMENT_SIZE_SAMPLES | SYS_P17074 | 19320 | ENABLED | ADVANCED |
| SEGMENT_SIZE_SAMPLES | SYS_P17075 | 24955 | ENABLED | ADVANCED |
| SEGMENT_SIZE_SAMPLES | SYS_P17076 | 24150 | ENABLED | ADVANCED |
| SEGMENT_SIZE_SAMPLES | SYS_P17077 | 24934 | ENABLED | ADVANCED |
How about existing indexes?
By default, existing non-unique indexes are also partitioned during the alteration of the table.
There are two indexes on my table, one unique index supporting the primary key constraint, and one non-unique index.
Before the table was altered, both were unpartitioned:
SELECT INDEX_NAME,UNIQUENESS, PARTITIONED FROM DBA_INDEXES WHERE TABLE_NAME='SEGMENT_SIZE_SAMPLES';
| INDEX_NAME | UNIQUENESS | PARTITIONED |
|---|---|---|
| SEGMENT_SIZE_SAMPLES_IDX1 | UNIQUE | NO |
| SEGMENT_SIZE_SAMPLES_IDX2 | NONUNIQUE | NO |
After the table was partitioned, the non-unique index was automatically partitioned, too:
| INDEX_NAME | UNIQUENESS | PARTITIONED |
|---|---|---|
| SEGMENT_SIZE_SAMPLES_IDX1 | UNIQUE | NO |
| SEGMENT_SIZE_SAMPLES_IDX2 | NONUNIQUE | YES |
Update 18.03.2020:
Another example using LIST partitioning:
alter table MUSIC.ALBUM modify
partition by list (GENRE)
(
partition P_ROCK values (( 'ROCK')),
partition P_POP values (( 'POP')),
partition P_CLASSICAL values (( 'CLASSICAL')),
partition P_MISC values (default)
)
online;
Update 12.03.2021:
An example using subpartitions:
-- First, give the LOB the desired attributes, if you wish to change any of them:
alter TABLE STOCKS MOVE
LOB (DOC)
STORE AS SECUREFILE(
TABLESPACE DATA1
ENABLE STORAGE IN ROW
CHUNK 8192
COMPRESS MEDIUM
);
-- Alter the table
alter TABLE STOCKS MODIFY
PARTITION BY LIST (stockname)
SUBPARTITION BY RANGE (LASTUPDATED)
( -- First partition is called a_name
PARTITION a_name VALUES('a-abc')
(
-- older values
SUBPARTITION SP_a_name_1_older VALUES LESS THAN ( TO_DATE('2016-01', 'YYYY-MM')) TABLESPACE DATA1
LOB (DOC) STORE AS SECUREFILE ( TABLESPACE DATA1 ),
-- 2016
subpartition SP_a_name_201601 VALUES LESS THAN (TO_DATE(' 2016-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')) TABLESPACE DATA_2016
LOB (DOC) STORE AS SECUREFILE ( TABLESPACE DATA_2016 ),
...continue with one subpartition per month per year...
...contine with partitions b_name, c_name etc
-- Final partition is called z_name
PARTITION z_name VALUES(default)
(
-- 2016
SUBPARTITION SP_sp_z_name_older VALUES LESS THAN ( TO_DATE('2016-01', 'YYYY-MM')) TABLESPACE DATA1,
subpartition SP_sp_z_name_201601 VALUES LESS THAN (TO_DATE(' 2016-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')) TABLESPACE DATA_2016
LOB (DOC) STORE AS SECUREFILE ( TABLESPACE DATA_2016 ),
...continue with one subpartition per month per year...
LOB (DOC) STORE AS SECUREFILE ( TABLESPACE DATA_2022 ),
subpartition SP_z_name_202212 VALUES LESS THAN (TO_DATE(' 2023-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS')) TABLESPACE DATA_2022
LOB (DOC) STORE AS SECUREFILE ( TABLESPACE DATA_2022 ),
SUBPARTITION SP_z_name_DEFAULT VALUES LESS THAN (MAXVALUE) TABLESPACE DATA1
LOB (DOC) STORE AS SECUREFILE ( TABLESPACE DATA1)
)
)
ONLINE
UPDATE INDEXES(
IDX_1 LOCAL,
IDX_2 LOCAL
);
Note that UPDATE INDEXES converts IDX_1 and IDX_2 and convert them to LOCAL indexes, on the fly.
Source: Oracle Documentation
I also recommend to look at Oracle-base.com for further reading.

No comments:
Post a Comment