Drop and recreate global index having list partition on the table - oracle

CREATE INDEX Index_name ON tab_name
(Co1)
GLOBAL PARTITION BY HASH (Co1);
I need to drop this global index having list partition with new column added
CREATE INDEX Index_name ON tab_name
(Co1,co2)
GLOBAL PARTITION BY HASH (Co1);
When I tried to drop and recreate the global indexes , I couldn't see the partitions
select partition_name from user_ind_partitions where index_name = 'Index_name'

I have specified the no of partitions at the end and its now able to retrieve all list partitions from table for the specified index .
CREATE INDEX Index_name ON tab_name
(Co1,co2)
GLOBAL PARTITION BY HASH (Co1,col2)
PARTITIONS 16;

Related

Moving data from one partition to another

I have a huge table containing about 500 million records. This table has 2 partitions, CURRENT_DATA and PREVIOUS_DATA.
When new data comes in, last PREVIOUS_DATA partition is truncated, and data from CURRENT_DATA partition is moved to PREVIOUS_DATA partition.
Right now, I am updating the records to move from one partition to another. However, it takes a long time. Is there any faster way to move data from one partition to another?
Don't strive to apply DML, but DROP, RENAME and MODIFY partitions as the partition previous_data is already been truncated such as
(presuming you have a list partition with VALUE = 'A' for the current, and VALUE = 'B' for the previous partitions)
ALTER TABLE tab
DROP PARTITION previous_data;
ALTER TABLE tab
RENAME PARTITION current_data TO previous_data;
ALTER TABLE tab
MODIFY PARTITION previous_data
ADD VALUES ('B');
ALTER TABLE tab
MODIFY PARTITION previous_data
DROP VALUES ('A');
ALTER TABLE tab
ADD PARTITION current_data VALUES ( 'A' );
Check out the partitions through
SELECT partition_name, high_value FROM USER_TAB_PARTITIONS WHERE table_name = 'TAB';
before and after applying those operations above(both cases should return the same results).
Be careful! Those are dangerous operation and shouldn't be tried within the production systems, but within the test databases !
If only goal is to separate current data from previous why not just to use two different tables PREVIOUS_DATA and CURRENT_DATA. You can easily get the complete picture by unioning the two together:
SELECT * FROM PREVIOUS_DATA
UNION ALL
SELECT * FROM CURRENT_DATA
When new data comes you can drop PREVIOUS_DATA table, rename CURRENT_DATA to PREVIOUS_DATA and then create new empty CURRENT_DATA table:
DROP TABLE PREVIOUS_DATA;
ALTER TABLE CURRENT_DATA RENAME TO PREVIOUS_DATA;
CREATE TABLE CURRENT_DATA AS SELECT * FROM PREVIOUS_DATA WHERE 1 = 2; /*add comments and constraints*/

How to move Indexes into another TableSpace

how to move indexes to another tablespace
select owner, index_name, TABLE_NAME, a.TABLESPACE_NAME
from all_indexes a where a.TABLE_NAME = 'REFUND';
ALTER INDEX CBS.PK_REFUND_ID REBUILD TABLESPACE T_IDX;
ORA-14086: A partitioned index may not be rebuilt as a whole.
I can't execute this statement because I don't know in which partition the index is
ALTER INDEX PK_REFUND_ID REBUILD PARTITION xxxxxx TABLESPACE T_IDX;
Because you also need partition name info which can be reached from user[all/dba]_tab_partitions dictionary view. If you got the related partition name, then
ALTER INDEX PK_REFUND_ID REBUILD PARTITION PR_REFUND_OLD [ONLINE];
might be used just to rebuild the index.
or
ALTER INDEX PK_REFUND_ID REBUILD PARTITION PR_REFUND_OLD [ONLINE] TABLESPACE T_IDX;
might be used to move the index of the partition to a different tablespace. Using ONLINE option would suit well for the tables currently having DML activity.
Use the following code in order to run as a batch job
DECLARE
v_ts_name VARCHAR2(35) := 'T_IDX';
BEGIN
FOR c IN
(
SELECT 'ALTER INDEX '||i.index_name||' REBUILD PARTITION '||p.partition_name||
' ONLINE TABLESPACE '||v_ts_name AS command
FROM user_part_indexes i
JOIN user_ind_partitions p
ON p.index_name = i.index_name
AND i.table_name = 'REFUND'
AND p.tablespace_name != v_ts_name
)
LOOP
EXECUTE IMMEDIATE c.command;
END LOOP;
END;
/

Right way to create index organized table

I am trying to create a index organized table in oracle 11. I create the index organized table and insert the row from another table.
create table salIOT (
mypk ,
cid ,
date,
CONSTRAINT sal_pk PRIMARY KEY (mypk)
) ORGANIZATION INDEX
AS Select * from another table;
But the leaf blocks are empty when I query
SQL> Select owner, index_name, table_name, leaf_blocks from all_indexes where table_name like 'SALIOT';
Am I missing something here?
You still need to gather statistics on the table, something like:
exec dbms_stats.gather_table_stats('ABC', 'IOTTableName')
(assuming 'ABC' is your username; change as needed) - then re-run your SELECT against ALL_INDEXES and you will see how many leaf blocks you have.

How to do partitioning and sub partitioning with exchange partition in Oracle?

I am facing issue with exchange partitioning and sub partitioning in Oracle.
Please explain with example.
Please find following example
CREATE TABLE DEPARTMENT
( DEPT_ID NUMBER(30,0) NOT NULL ENABLE,
IS_ACTIVE VARCHAR2(1 BYTE) NOT NULL ,
BUSINESS_DATE DATE NOT NULL ENABLE,
COMPANY_CODE VARCHAR2(4) DEFAULT 'C1' NOT NULL ,
CONSTRAINT PK_DEPARTMENT PRIMARY KEY (BUSINESS_DATE, COMPANY_CODE, DEPT_ID) ENABLE
)
PARTITION BY RANGE
(
BUSINESS_DATE
)
INTERVAL (
NUMTODSINTERVAL(1,'DAY')
)
SUBPARTITION BY LIST(COMPANY_CODE)
SUBPARTITION TEMPLATE
(
SUBPARTITION CMN_01 VALUES ('C1'),
SUBPARTITION CMN_02 VALUES ('C2'),
SUBPARTITION CMN_03 VALUES ('C3')
)
(
PARTITION DEFAULT_PART VALUES LESS THAN ('01-JAN-2012')
)
;
CREATE INDEX IDX1_DEPARTMENT ON DEPARTMENT (DEPT_ID, IS_ACTIVE);
CREATE TABLE TEMP_DEPARTMENT AS SELECT * FROM DEPARTMENT WHERE 1=2;
CREATE TABLE EMPLOYEE
( ID NUMBER(30,0) NOT NULL ENABLE,
DEPT_ID NUMBER(30,0) NOT NULL ENABLE,
BUSINESS_DATE DATE NOT NULL ENABLE,
COMPANY_CODE VARCHAR2(4) DEFAULT 'C1' NOT NULL,
CONSTRAINT PK_EMPLOYEE PRIMARY KEY (BUSINESS_DATE,COMPANY_CODE, ID) ENABLE,
CONSTRAINT FK1_EMPLOYEE_DEPT FOREIGN KEY (BUSINESS_DATE, COMPANY_CODE, DEPT_ID)
REFERENCES DEPARTMENT (BUSINESS_DATE, COMPANY_CODE, DEPT_ID) ENABLE NOVALIDATE
)
PARTITION BY RANGE
(
BUSINESS_DATE
)
INTERVAL (
NUMTODSINTERVAL(1,'DAY')
)
SUBPARTITION BY LIST(COMPANY_CODE)
SUBPARTITION TEMPLATE
(
SUBPARTITION CMN_01 VALUES ('C1'),
SUBPARTITION CMN_02 VALUES ('C2'),
SUBPARTITION CMN_03 VALUES ('C3')
)
(
PARTITION DEFAULT_PART VALUES LESS THAN ('01-JAN-2012')
);
Insert few thousands records into DEPARTMENT and EMPLOYEE tables for few partitions and their all sub partitions
select * from DEPARTMENT where BUSINESS_DATE='19-JAN-15' and COMPANY_CODE='C1';
select* from EMPLOYEE;
select * from all_tab_partitions where TABLE_OWNER='TEST' and
table_name='DEPARTMENT';
select * from ALL_TAB_SUBPARTITIONS where TABLE_OWNER='TEST' and
table_name='DEPARTMENT';
select * from all_tab_partitions where TABLE_OWNER='TEST' and
table_name='EMPLOYEE';
select * from ALL_TAB_SUBPARTITIONS where TABLE_OWNER='TEST' and
table_name='EMPLOYEE';
select * from TEMP_DEPARTMENT;
Exchange and Truncate sub partitions
1)Exchange sub partitioningALTER TABLE DEPARTMENT EXCHANGE SUBPARTITION SYS_SUBP7356 WITH TABLE TEMP_DEPARTMENT WITHOUT VALIDATION UPDATE GLOBAL INDEXES;
2) Truncate temp exchange table truncate table TEMP_DEPARTMENT;
3) Truncate sub partitioning (sub partition name from ALL_TAB_SUBPARTITIONS table) with global index update `ALTER TABLE DEPARTMENT TRUNCATE SUBPARTITION SYS_SUBP7356 DROP STORAGE UPDATE GLOBAL INDEXES;
Here the above 1 to 3 steps are executed for three sub-partitions
4) Get this partition name from all_tab_partitions table with global index update ALTER TABLE DEPARTMENT DROP PARTITION SYS_P7359 UPDATE GLOBAL INDEXES;
5) Truncate sub partitioning (sub partition name from ALL_TAB_SUBPARTITIONS table) with global index update ALTER TABLE EMPLOYEE TRUNCATE SUBPARTITION SYS_SUBP7360 DROP STORAGE UPDATE GLOBAL INDEXES;
Here the above 5 steps are executed for three sub-partitions
6) Get this partition name from all_tab_partitions table with global index update ALTER TABLE EMPLOYEE DROP PARTITION SYS_P7363 UPDATE GLOBAL INDEXES;
7) alter index PK_DEPARTMENT rebuild;
8) alter index IDX1_DEPARTMENT rebuild;
9) alter index PK_EMPLOYEE rebuild;
Steps 7 to 9 is require only when UPDATE GLOBAL INDEXES not used at the time of Altering Table for exchange, truncate and drop partition or sub partition
10)
begin
dbms_stats.gather_table_stats(ownname=>'TEST', tabname=>'DEPARTMENT', granularity=>'ALL' ,no_invalidate=>FALSE);
dbms_stats.gather_table_stats(ownname=>'TEST', tabname=>'EMPLOYEE', granularity=>'ALL' ,no_invalidate=>FALSE);
end;
UPDATE GLOBAL INDEXES is used at the time of Altering Table for exchange, truncate and drop partition or sub partition where global indexes are applied on that table then we can do DML operation on same table in parallel here.
UPDATE GLOBAL INDEXES is used to rebuild the indexes at same time with alter operation.
If UPDATE GLOBAL INDEXES is not used then DML operation is not allowed on same table in parallel. It will throw below ORA Exception for global indexes.
ERROR Message when perform insert operation after drop/exchange/truncate partition/sub partition from table:
SQL Error: ORA-01502: index 'TEST.PK_DEPARTMENT' or partition of such
index is in unusable state
01502. 00000 - "index '%s.%s' or partition of such index is in unusable state"
Cause: An attempt has been made to access an index or index partition that has been marked unusable by a direct load or by a DDL operation
Action: DROP the specified index, or REBUILD the specified index, or REBUILD the unusable index partition
If you don’t want to use UPDATE GLOBAL INDEXES and want parallel DML operation with purging then make indexes Local (must not contain primary key or unique constraint because it is default created global unique index). It’s on partition and sub partition and refers default table space.
With Local indexes you observed slow insertion on that table.

About create table as select (CTAS)

When we do:
create table big2 as select * from big1;
Are the indexes and constraints also copied over to the new table?
Only NOT NULL constraints are copied. See FAQ.
You can do CREATE TABLE big2 (bigid PRIMARY KEY) AS SELECT * FROM big1 tp create a primary key, but yes, for other indexes you'll want to copy and run the index creation scripts.
Just for info, there is a simple way to remember indices to recreate them after deleting source table:
SELECT DBMS_METADATA.get_ddl('INDEX', index_name)
FROM user_indexes
WHERE TABLE_NAME = 'BIG1';

Resources