Find the sub-partitions that you would like to relocate:
SELECT TABLE_OWNER,TABLE_NAME,COLUMN_NAME,LOB_NAME,SUBPARTITION_NAME,LOB_PARTITION_NAME,SECUREFILE,TABLESPACE_NAME FROM DBA_LOB_SUBPARTITIONS WHERE TABLE_OWNER = 'SCOTT' AND TABLESPACE_NAME = 'USERS';
TABLE_OWNER | TABLE_NAME | COLUMN_NAME | LOB_NAME | SUBPARTITION_NAME | LOB_PARTITION_NAME | SECUREFILE | TABLESPACE_NAME |
---|---|---|---|---|---|---|---|
SCOTT | TMP_POSK_LEVERANSER | TOTALER | SYS_LOB0000093760C00010$$ | P_2013_P_AMELDING | SYS_LOB_P441 | NO | USERS |
SCOTT | TMP_POSK_LEVERANSER | TOTALER | SYS_LOB0000093760C00010$$ | P_2013_P_DEFAULT | SYS_LOB_P441 | NO | USERS |
SCOTT | TMP_POSK_LEVERANSER | XML_INNHOLD | SYS_LOB0000093760C00020$$ | P_2013_P_AMELDING | SYS_LOB_P447 | NO | USERS |
SCOTT | TMP_POSK_LEVERANSER | XML_INNHOLD | SYS_LOB0000093760C00020$$ | P_2013_P_DEFAULT | SYS_LOB_P447 | NO | USERS |
SCOTT | TMP_POSK_LEVERANSER | OPPSUMMERING | SYS_LOB0000093760C00021$$ | P_2013_P_AMELDING | SYS_LOB_P453 | NO | USERS |
SCOTT | TMP_POSK_LEVERANSER | OPPSUMMERING | SYS_LOB0000093760C00021$$ | P_2013_P_DEFAULT | SYS_LOB_P453 | NO | USERS |
See this post for a more advanced variant that will also show the size of each LOB subpartition
Some examples of correct syntax to move such LOB segments are given below:
-- move a basicfile LOB alter table SCOTT.TMP_POSK_LEVERANSER move subpartition P_2013_P_AMELDING lob (TOTALER) store as basicfile (tablespace DATA1); -- move a securefile LOB. Allow for DML and make sure global indexes are not rendered unusable alter table SCOTT.TMP_POSK_LEVERANSER move subpartition P_2013_P_DEFAULT lob (OPPSUMMERING) store as securefile (tablespace DATA1) ONLINE UPDATE GLOBAL INDEXES; -- move a securefile LOB and compress it alter table SCOTT.TMP_POSK_LEVERANSER move subpartition P_2013_P_MELDING lob (PDFATTACHMENT) store as securefile (tablespace LOB_DATA COMPRESS MEDIUM);'
Generate the DDLs:
SELECT 'alter table ' || TABLE_OWNER || '.' || TABLE_NAME || ' move subpartition ' || SUBPARTITION_NAME || ' lob (' || COLUMN_NAME || ') store as securefile|basicfile(tablespace DATA1 compress LOW|MEDIUM|HIGH) ONLINE UPDATE GLOBAL INDEXES;' FROM DBA_LOB_SUBPARTITIONS WHERE TABLE_OWNER = 'SCOTT' AND TABLESPACE_NAME = 'USERS' -- to limit your script to certain subpartitions only, uncomment the line below -- AND SUBPARTITION_NAME='MY_SUBPART_NAME' ;
I have used this script successfully in the past, which generates a log file and sets MODULE and ACTION etc in its session:
accept table_owner prompt 'Table owner: ' accept table_name prompt 'Table name: ' accept new_tabspc prompt 'New tablespace: ' accept old_tabspc prompt 'Old tablespace: ' set lines 300 set heading off set feedback off set verify off set echo off set pages 0 set trimspool on spool exec_move_lob_&&table_owner..&&table_name..sql select 'alter session set nls_language=''american'';' from dual; select 'alter session force parallel ddl;' from dual; select 'set timing on' from dual; select 'set lines 200' from dual; select 'set trimspool on' from dual; select 'spool exec_move_lob_&&table_owner..&&table_name..log' from dual; select 'exec DBMS_APPLICATION_INFO.SET_MODULE(module_name=>''Move'', action_name=>''MoveLOB_&&table_name'');' from dual; select 'exec DBMS_APPLICATION_INFO.SET_CLIENT_INFO (client_info=>''MoveLOB_&&table_name'');' from dual; select 'exec DBMS_SESSION.SET_IDENTIFIER (client_id=>''MoveLOB_&&table_name''); ' from dual; SELECT 'alter table ' || ts.TABLE_OWNER || '.' || ts.TABLE_NAME || ' move subpartition ' || lsp.subpartition_name || ' lob (' || lsp.column_name || ') store as securefile (tablespace &&new_tabspc COMPRESS MEDIUM) ONLINE UPDATE GLOBAL INDEXES;' FROM dba_segments s JOIN dba_lob_subpartitions lsp ON (s.partition_name = lsp.lob_subpartition_name) JOIN DBA_TAB_SUBPARTITIONS ts ON (TS.SUBPARTITION_NAME = lsp.SUBPARTITION_NAME) WHERE lsp.table_name = '&&table_name' AND ts.table_name = '&&table_name' -- To limit the output to a specific tablespace, uncomment the line below --AND s.tablespace_name = '&&old_tabspc' AND ts.table_owner = '&&table_owner' -- To limit output to specific table subpartitions only, uncomment the following row --AND lsp.subpartition_name like 'SYS_SUBP186786%' AND s.segment_name IN ( SELECT lpt.lob_name FROM dba_lob_partitions lpt WHERE lpt.table_name IN ( '&&table_name' ) ) GROUP BY ts.table_owner,ts.table_name,s.SEGMENT_NAME,s.SEGMENT_TYPE,s.SEGMENT_SUBTYPE,s.PARTITION_NAME,lsp.COMPRESSION,lsp.subpartition_name, lsp.column_name,ts.num_rows,lsp.tablespace_name -- To limit output to lob subpartitions with a specific size, uncomment the restriction above and change the operator to suit your needs ( <, >, =, =>, <= or use BETWEEN x AND y) --HAVING ROUND(sum(s.bytes)/1024/1024/1024) between 1 and 10 ORDER BY lsp.subpartition_name DESC; select 'exit' from dual; exit