We have a VLDB around 2TB and tables are partitioned on each date. We also have index mapping for these partitions. But for year 2019 all the data up to 01-Oct-2019 is getting into a single partition as due to a typo a single sub partition got created with a high value of 01/10/2019.
We are trying to correct this using Split Partition i.e. move data up to 10th Feb 2019 to single partition and then remove the empty partition and create single partitions for each date. This is working fine.
The issue is coming with index mapping as there are mappings already from 1st Oct to 31st Dec and we are not able to drop these. So we were trying to create mapping from 11 Feb till 30 Sep. The script for this is taking a very long time due to volume of data. And also the indexes goes into UNUSABLE state after this and when we try to rebuild it's taking ages!!
Is there any better way we can do it.
CODE SAMPLE-
CREATE TABLE My_Table (
id NUMBER(9,0) NOT NULL,
source_system VARCHAR(20),
eod_date NUMBER(9,0) NOT NULL,
other columns
)
TABLESPACE XYZ001td
PARTITION BY LIST (source_system)
SUBPARTITION BY RANGE (
eod_date
)
(
PARTITION p_XYZ VALUES ('XYZ')
NOCOMPRESS
(
SUBPARTITION XYZ_20181227 VALUES LESS THAN (20181228) TABLESPACE XYZ_20181227_td,
SUBPARTITION XYZ_20181228 VALUES LESS THAN (20181229) TABLESPACE XYZ_20181228_td,
SUBPARTITION XYZ_20181229 VALUES LESS THAN (20181230) TABLESPACE XYZ_20181229_td,
SUBPARTITION XYZ_20181230 VALUES LESS THAN (20181231) TABLESPACE XYZ_20181230_td,
SUBPARTITION XYZ_20181231 VALUES LESS THAN (20190101) TABLESPACE XYZ_20181231_td
**SUBPARTITION XYZ_20191001 VALUES LESS THAN (20191002) TABLESPACE XYZ_20191001_td,**
SUBPARTITION XYZ_20191002 VALUES LESS THAN (20191003) TABLESPACE XYZ_20191002_td,
SUBPARTITION XYZ_20191003 VALUES LESS THAN (20191004) TABLESPACE XYZ_20191003_td,
)
)
/
CREATE INDEX inx_my_table_01
ON My_table (
source_system,
eod_date
)
TABLESPACE XYZ001td
GLOBAL PARTITION BY HASH (
source_system,
eod_date
)
(
PARTITION XYZ_20181227
TABLESPACE XYZ_20181227_ti
LOGGING,
PARTITION XYZ_20181228
TABLESPACE XYZ_20181228_ti
LOGGING,
PARTITION XYZ_20181229
TABLESPACE XYZ_20181229_ti
LOGGING,
PARTITION XYZ_20181230
TABLESPACE XYZ_20181230_ti
LOGGING,
PARTITION XYZ_20181231
TABLESPACE XYZ_20181231_ti
LOGGING
)
i am not sure if i completely understand the problem. But i think following steps might help
Create a temp table and copy all 2019 data to that table
drop all 2019 partitions and indexes.
recreate partitions and re insert the data
create local indexes
We can not drop global hash-partitioned index
ORA-14330: Cannot drop a partition of a global hash-partitioned index
Is there any way to insert intermediate Index mapping without touching existing Index mapping
Related
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
I'm creating a database which will utilize composite partitioning. I will partition one table using range partitioning (by date)
and then further subpartition it by hash (by client id). So far so good, no problem, but I also need to have those partitions
stored in separate data files each dbf holding data for a single month. I'm reading on composite partitions and what I found
is that primary range partitioning will be only a logical one and data will be stored in subpartitions instead which seems to
make my goal impossible. Am I right and should look for a different solution?
Thanks in advance.
My databases are Oracle 11g and Oracle 12
On existing table you can move partitions or subpartitions to a different tablespace, i.e. different datafile, examples:
ALTER TABLE scuba_gear MOVE SUBPARTITION bcd_types TABLESPACE tbs23;
ALTER TABLE parts MOVE PARTITION depot2 TABLESPACE ts094;
see Moving Subpartitions and Moving Table Partitions
For new tables typically you would be create them like this:
CREATE TABLE sales
( prod_id NUMBER(6)
, cust_id NUMBER
, time_id DATE
, channel_id CHAR(1)
, promo_id NUMBER(6)
, quantity_sold NUMBER(3)
, amount_sold NUMBER(10,2)
)
PARTITION BY RANGE (time_id)
INTERVAL (NUMTOYMINTERVAL(1,'MONTH'))
STORE IN (ts_1, ts_2, ts_3, ts_4, ts_5, ts_6 ,ts_7 ,ts_8, ts_9, ts_10, ts_11, ts_12)
SUBPARTITION BY HASH (cust_id) SUBPARTITIONS 4
( PARTITION before_2000 VALUES LESS THAN (TO_DATE('01-JAN-2000','dd-MON-yyyy')));
Oracle then will put the monthly partitions by "round-robin" method to these 12 tablespaces. STORE IN clause is also possible for subpartitions, see Creating a composite range-hash partitioned table
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)
I need to change the tablespace where 7 indexes are created. This is a 3TB partitioned index. A new partition is created each day and then folded into months. The command I am running is
alter index myindex1 modify default attributes for partition
mypartition tablespace myNewIndexTablespace;
The error is
ORA-14288 index is not partitioned by composite range method Cause:
The index in a partition or subpartition maintenance operation command
must be partitioned by composite range method.
I am trying to figure out the best approach here considering these indexes are big and reside on 52 partitions.
I think that this means that you cannot define a default tablespace for an index partition if that partition does not contain subpartitions.
The reason for that would be that the default tablespace for an object is the one to which new partitions or subpartitions would be assigned on creation. If a table or index is not partitioned then of course it could not have a default tablespace for new partitions, and if a table or index partition is not subpartitioned then it cannot have a default tablespace for the addition of new subpartitions.
You probably want to:
alter index
myindex1
modify
default attributes
tablespace myNewIndexTablespace;
... and then rebuild the current index partitions to the new tablespace.
http://docs.oracle.com/cd/E11882_01/server.112/e26088/statements_1010.htm#i2129868
Apart from the obvious, can anyone explain the what is different between multicolumn partitioning and using a subpartition? And which one is better for a OLTP scenario? For details, see Managing Partitioned Tables and Indexes in the Oracle Database Administrator's Guide.
A (dumb) example of a table partitioned on multiple columns is:
CREATE TABLE demo1
(
year NUMBER,
month NUMBER,
day NUMBER,
instance NUMBER, /* assuming this can only be 1 or 2 */
other1 VARCHAR2(50),
other2 VARCHAR2(50),
other3 VARCHAR2(50)
)
PARTITION BY RANGE (year,instance)
(
PARTITION data_2009_inst1 VALUES less than (2009,2) TABLESPACE data_2009,
PARTITION data_2009_inst2 VALUES less than (2009,3) TABLESPACE data_2009,
PARTITION data_2010_inst1 VALUES less than (2010,2) TABLESPACE data_2010,
PARTITION data_2010_inst2 VALUES less than (2010,3) TABLESPACE data_2010,
PARTITION data_2011_inst1 VALUES less than (2011,2) TABLESPACE data_2011,
PARTITION data_2011_inst2 VALUES less than (2011,3) TABLESPACE data_2011
);
Similarly, example of a subpartitioned table is:
CREATE TABLE demo2
(
year NUMBER,
month NUMBER,
day NUMBER,
instance NUMBER, /* assuming this can only be 1 or 2 */
other1 VARCHAR2(50),
other2 VARCHAR2(50),
other3 VARCHAR2(50)
)
PARTITION BY RANGE (year)
SUBPARTITION BY LIST (instance) /* Cannot subpartition by range in 10gR2 */
SUBPARTITION template
(
SUBPARTITION i1 VALUES (1),
SUBPARTITION i2 VALUES (2),
SUBPARTITION ix VALUES (DEFAULT)
)
(
PARTITION data_2009 VALUES less than (2010) TABLESPACE data_2009,
PARTITION data_2010 VALUES less than (2011) TABLESPACE data_2010,
PARTITION data_2011 VALUES less than (2012) TABLESPACE data_2011
);
Now what is the difference between these tables? Are they not "logically" the same? I know its far easier to add partitions to demo2 as you need to split partitions on demo1 to get more partitions as time passes by. Which on is better in an OLTP scenario?
On a side note, the reason I am partitioning on the INSTANCE number has to do with Oracle RAC. I am trying to create an "instance affinity" to stop "hot block" from slowing down the database as these need be sent across the interconnect between the RAC nodes. (We have empirically proved that this does make a difference in our testing).
There probably isn't any difference in your case, but in general sub-partitioning allows you to partition in 2 different ways, such as range-hash, range-list. Your sub-partition example is range-list, but equivalent to the single-level range partitioning. However, you could not use a single-level if your sub-partitioning was like this example from the doc you linked:
ALTER TABLE quarterly_regional_sales
ADD PARTITION q1_2000 VALUES LESS THAN (TO_DATE('1-APR-2000','DD-MON-YYYY'))
STORAGE (INITIAL 20K NEXT 20K) TABLESPACE ts3 NOLOGGING
(
SUBPARTITION q1_2000_northwest VALUES ('OR', 'WA'),
SUBPARTITION q1_2000_southwest VALUES ('AZ', 'UT', 'NM'),
SUBPARTITION q1_2000_northeast VALUES ('NY', 'VM', 'NJ'),
SUBPARTITION q1_2000_southeast VALUES ('FL', 'GA'),
SUBPARTITION q1_2000_northcentral VALUES ('SD', 'WI'),
SUBPARTITION q1_2000_southcentral VALUES ('OK', 'TX')
);
One advantage of sub-partitions is that they allow individual fine-grained management of the sub-partitions. For example in a data archive table lets say there are different retention requirements based not only on the date, but another value as well.
Using your example perhaps you are required to keep data with value instance = 1 for 7 years, but data with instance = 2 can be discarded after 4 years. Sub-partitioning would allows you to drop the sub-partitions containing data with instance = 2 independently of the other values.