ORACLE EXCHANGE PARTITION and PARTITION INDEXES - oracle

In order to compress the data in a single partition, I use the following approach:
-- I create a table with the same structure of the ORIGINAL TABLE, but
-- on a new tablespace (NEW_TBS_DATA)
CREATE TABLE AUXILIARY_TABLE TABLESPACE NEW_TBS_DATA AS
SELECT * FROM ORIGINAL_TABLE WHERE 1=0
-- I create the index on the AUXILIARY_TABLE, on a new tablespace
-- for indexes (NEW_TBS_IDX)
CREATE INDEX I_1 ON AUXILIARY_TABLE( START_DATE) TABLESPACE NEW_TBS_IDX
CREATE INDEX I_2 ON AUXILIARY_TABLE( ID_FILE) TABLESPACE NEW_TBS_IDX
CREATE INDEX I_3 ON AUXILIARY_TABLE( DESCRIPTION) TABLESPACE NEW_TBS_IDX
CREATE INDEX I_4 ON AUXILIARY_TABLE( ZIP_CODE) TABLESPACE NEW_TBS_IDX
CREATE INDEX I_5 ON AUXILIARY_TABLE( BH_TRAFFIC) TABLESPACE NEW_TBS_IDX
-- I move data from partition 20160529 to auxiliary_table
ALTER TABLE ORIGINAL_TABLE EXCHANGE PARTITION PARTITION_20160529 WITH TABLE AUXILIARY_TABLE INCLUDING INDEXES WITHOUT VALIDATION
-- I compress data using the new tablespace NEW_TBS_DATA on auxiliary_table
ALTER TABLE AUXILIARY_TABLE MOVE TABLESPACE NEW_TBS_DATA PARALLEL 4 COMPRESS
-- I move the data back to the original table, with the same exchange statement:
ALTER TABLE ORIGINAL_TABLE EXCHANGE PARTITION PARTITION_20160529 WITH TABLE AUXILIARY_TABLE including indexes without validation
-- I drop the auxiliary_table
DROP TABLE AUXILIARY_TABLE CASCADE CONSTRAINTS PURGE
Why, at the end of the process, the partition INDEXES are on the old tablespace instead of the new tablespace (NEW_TBS_IDX)?

Section "including indexes" takes affect only for local indexes. See
https://docs.oracle.com/cd/E11882_01/server.112/e25523/part_admin002.htm
section(Exchanging Partitions)

Related

ORA-14287 Rebuilding a composite partitioned index on new tablespace

Trying to move composite index partitions from tablespace A to tablespace B.
First I have moved all subpartitions successfully using DDL
ALTER INDEX idx1 REBUILD SUBPARTITION "0001234567889_1" TABLESPACE tablespace1 ONLINE PARALLEL;
dba_ind_subpartitions is now empty on originating tablespace. However indexes in dba_ind_partitions are still pointing to old tablespace. How do i change the tablespace of composite partitioned index?
I have tried rebuilding the indexes unsuccessfull:
SQL> ALTER INDEX idx1 REBUILD PARTITION "0001234567" TABLESPACE tablesspace1 ONLINE PARALLEL
*
ERROR at line 1:
ORA-14287: cannot REBUILD a partition of a composite partitioned index
EDIT:
Is it no possible to rebuild the indexes? Do i need to drop and recreate?
You have composite-partitioned table, so this is normal situation.
https://docs.oracle.com/database/121/VLDBG/GUID-E3F353CB-9748-44D4-B7B1-4BBAAF618D9D.htm
In your case on table or partition level you can modify default attributes.
https://docs.oracle.com/database/121/VLDBG/GUID-C003E6DB-3867-4407-86D2-A51F30AF07CC.htm#VLDBG1177

Move LOB tablespace on partitioned tables

Consider following tables:
CREATE TABLE TAB_ONE
(
<irrelevant columns>
MESSAGE CLOB,
REC_DATE DATE,
<irrelevant columns>
) TABLESPACE DATA_TS;
and
CREATE TABLE TAB_TWO
(
<irrelevant columns>
RESPONSE CLOB,
PART_ID NUMBER,
<irrelevant columns>
CONSTRAINT "FK_01"
FOREIGN KEY ("PART_ID") REFERENCES <IRRELEVANT_TABLE> ("SEQ_ID")
) TABLESPACE DATA_TS PARTITION BY REFERENCE (FK_01) ENABLE ROW MOVEMENT;
now, the task is to move all the (C)LOBs from DATA_TS to newly allocated tablespace called LOB_TS.
For the first table, it is easy enough:
ALTER TABLE TAB_ONE MOVE LOB ("MESSAGE") store as (tablespace LOB_TS compress low);
For the other one, partitioning does all the trouble. The aforementioned command does not work for obvious reasons, so I managed to find another:
ALTER TABLE TAB_TWO MOVE PARTITION SYS_P18485 LOB (RESPONSE) STORE AS ( TABLESPACE LOB_TS COMPRESS LOW );
ALTER TABLE TAB_TWO MOVE PARTITION SYS_P18299 LOB (RESPONSE) STORE AS ( TABLESPACE LOB_TS COMPRESS LOW );
(one for each partition the table TAB_TWO has)
These ALTER TABLES do not fail per se. The SQL Developer proudly states "Table TAB_TWO altered."
But then I ran SELECT * FROM USER_LOBS WHERE TABLE_NAME = 'TAB_TWO' and found out, that the CLOB stayed in the previous tablespace and did not move.
Of course, the idea of copying data via Create Table as Select, dropping the table, creating a new table and restoring the data occurred to me, but I would prefer a cleaner solution without the need of duplicating large amounts of data to different tables.

PL/SQL Creating a table with indexes

I have the following PL/SQL code:
DROP TABLE TAB_PARAM;
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE TAB_PARAM
(
TABLE_OWNER VARCHAR2(30) NOT NULL,
TABLE_NAME VARCHAR2(30) NOT NULL,
COLUMN_NAME VARCHAR2(30) NOT NULL,
PATTERN VARCHAR2(1024),
TYPE_METHODE VARCHAR2(30) NOT NULL,
SEPARATEUR VARCHAR2(20),
ID VARCHAR2(30),
CONSTRAINT PK_TAB_PARAM PRIMARY KEY (TABLE_OWNER,TABLE_NAME,COLUMN_NAME) USING INDEX TABLESPACE IND_PARC_256M NOLOGGING
)
TABLESPACE TAB_PARC_256M NOLOGGING NOCACHE NOMONITORING NOPARALLEL';
commit;
END;
/
I don't understand the part :
CONSTRAINT PK_TAB_PARAM PRIMARY KEY (TABLE_OWNER,TABLE_NAME,COLUMN_NAME) USING INDEX TABLESPACE IND_PARC_256M NOLOGGING
Nor the part:
TABLESPACE TAB_PARC_256M NOLOGGING NOCACHE NOMONITORING NOPARALLEL';
I know that it is setting the ID as primary key of TAB_PARAM but then I do not get the index part.
Can anyone help me understand this code please?
Sometimes you can create a table in a disposable way , for example you need to read data via sqlloader from file and insert in table , after that you will select all records from table . This operation doesnt need indexes and doesnt need primary key . Anyway it is always good to create primary key when you create a table and Oracle will create index for you . You can create more indexes whenever you want since the table was created . Now suppose you wanna update the table using where condition on a field who is not a primary key , it could be a better decision create an index on that field . In addition when you create indexes or table , you can associate tablespaces (created before) and could be good practice separate tablespaces for tables and indexes . All those operations are DDL Statements . In Oracle you can check datafiles , tables and indexes with those queries select * from dba_data_files; select * from dba_tables; select * from dba_indexes;
For primary key oracle implicitly creates unique index in table's tablespace.
This part USING INDEX TABLESPACE allow us to indicate tablespace for this implicitly index.
NOLOGGING - data is modified with minimal logging (to mark new extents invalid and to record dictionary changes).
NOCACHE - Oracle doesn't store blocks in the buffer cache.
NOPARALLEL - Parallel execution is not allowed on this table.(Default value)
NOMONITORING - Disable statistics collection. Now is deprecated. There is other mechanism to collect statistic
Edit. from oracle doc
Oracle Database uses an existing index if it contains a unique set of values before enforcing the primary key constraint. The existing
index can be defined as unique or nonunique. When a DML operation is
performed, the primary key constraint is enforced using this existing
index.
If there already index hitting the pk columns , oracle will used it, else then Oracle Database generates a unique index.
so you can create a primary key in oracle without an index if there was already index for that columns , specifying an index is for performance issue. The purpose of an index in a table is to 'read' the data faster.
From the oracle document
An index is a schema object that contains an entry for each value that
appears in the indexed column(s) of the table or cluster and provides
direct, fast access to rows.
As for the TABLESPACE, its where the database object exists, so when you create a table you specify in which tablespace you want it to exists. Read more here oracle document
As for NOLOGGING NOCACHE NOMONITORING, so the table not to be logged in redo logs or cached, also related to performance issue.

How do you add a CLOB column with a separate tablespace to an existing Oracle table?

I'm trying to add a CLOB column with a separate tablespace to an existing Oracle table. The existing table, "articles":
create table articles (
id number,
title varchar2(100),
published timestamp;
) tablespace TS_DATA;
has no CLOB columns. I've created a separate tablespace to hold the CLOB data:
create tablespace TS_LOB
datafile size 1024M autoextend on next 1024M maxsize 32767M;
When I try the following to add the CLOB column to "articles" as SYS using:
alter table articles add (content clob)
lob (content) store as basicfile art_content_seg (tablespace TS_LOB);
I get:
ORA-01950: no privileges on tablespace 'TS_LOB'
There is plenty of space on disk to accommodate the tablespace.
SOLUTION
I found the problem. I needed to issue:
alter user <TABLE OWNER> quota unlimited on TS_LOB;
Previously I had issued:
grant unlimited tablespace to <TABLE OWNER>;
But that didn't work.

Oracle Database: How can I alter a partitioned table to a new table space for not only the partitions but also the table itself?

How can I alter a partitioned table (in Oracle 10g Database) to a new table space for not only the partitions but also the table itself? Which I mean is, I can do following without issues,
--sql
alter table abc move partition abc01 tablespace new_tablespace;
alter table abc move partition abc02 tablespace new_tablespace;
alter table abc move partition abc03 tablespace new_tablespace;
but somehow the table's definition is still associating with the old table space, and and I have moved all tables data off the old table space. If I query the dba_segment for the old table space, there is nothing there. My question is, may I drop the old table space, even no data in the data files in the old table space, but somehow those partitioned tables definitions still associating with the old table space?
Each partition must be moved, as you've discovered. If you want new partitions to be created in a different tablespace without specifying that new tablespace, you'd have to use the following:
alter table abc modify default attributes tablespace new_tablespace;

Resources