Home>Question Details



arun -- Thanks for the question regarding "Indexes on single Partition of the table", version 10.2.0

Submitted on 2-Apr-2008 15:17 Central time zone
Last updated 7-Oct-2011 16:25

You Asked

I have a table which has been partitioned by the months.Also in the same
table i have an indexes in 4 columns. I used partition as we will be loading the data everymonth. We will be having around 9 million rows everymonth.
While inserting the rows its being slow as i have indexes.The main reason for having index is that the data is being pulled every now and then for different purposes.
As of now, i am dropping the index while loading the data and re Creating once the data has been loaded. But what i see here is everytime i am dropping the index it is dropping the index and recreating in the whole table.It does not matter much right now as i only have data for the partition of JAn and Feb.

But as time goes and my data is being filled in every partition, dropping the index and recreating index again would cost more than not doing it.
SO the question is how can i can drop the index for a single partition of the table and recreate it. so that i dont have to recreate the index for all the partition.
IF not ,what would be the best solution?

and we said...

you can set an individual local index partition unusable, load partition and then just rebuild that local index partition.

ops$tkyte%ORA10GR2> CREATE TABLE t
  2  (
  3    dt  date,
  4    x   int,
  5    y   varchar2(30)
  6  )
  7  PARTITION BY RANGE (dt)
  8  -- subpartition by hash(x)
  9  (
 10    PARTITION part1 VALUES LESS THAN (to_date('13-mar-2003','dd-mon-yyyy')) ,
 11    PARTITION part2 VALUES LESS THAN (to_date('14-mar-2003','dd-mon-yyyy'))
 12  )
 13  /

Table created.

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> create index t_idx on t(x) LOCAL;

Index created.

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> insert into t select to_date('12-mar-2003','dd-mon-yyyy'), rownum, 
object_name from user_objects;

298 rows created.

ops$tkyte%ORA10GR2> commit;

Commit complete.

ops$tkyte%ORA10GR2> select 'part1', count(*) from t partition(part1) union all select 
'part2', count(*) from t partition(part2);

'PART   COUNT(*)
----- ----------
part1        298
part2          0

ops$tkyte%ORA10GR2> select partition_name, status from user_ind_partitions where 
index_name='T_IDX' order by 1;

PARTITION_NAME                 STATUS
------------------------------ --------
PART1                          USABLE
PART2                          USABLE

ops$tkyte%ORA10GR2> alter index t_idx modify partition part2 unusable;

Index altered.

ops$tkyte%ORA10GR2> select partition_name, status from user_ind_partitions where 
index_name='T_IDX' order by 1;

PARTITION_NAME                 STATUS
------------------------------ --------
PART1                          USABLE
PART2                          UNUSABLE

ops$tkyte%ORA10GR2> show parameter skip

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
skip_unusable_indexes                boolean     TRUE
ops$tkyte%ORA10GR2> insert into t select to_date('13-mar-2003','dd-mon-yyyy'), rownum, 
object_name from user_objects;

298 rows created.

ops$tkyte%ORA10GR2> commit;

Commit complete.

ops$tkyte%ORA10GR2> select 'part1', count(*) from t partition(part1) union all select 
'part2', count(*) from t partition(part2);

'PART   COUNT(*)
----- ----------
part1        298
part2        298

ops$tkyte%ORA10GR2> select partition_name, status from user_ind_partitions where 
index_name='T_IDX' order by 1;

PARTITION_NAME                 STATUS
------------------------------ --------
PART1                          USABLE
PART2                          UNUSABLE

ops$tkyte%ORA10GR2> alter index t_idx rebuild partition part2 ;

Index altered.

ops$tkyte%ORA10GR2> select partition_name, status from user_ind_partitions where 
index_name='T_IDX' order by 1;

PARTITION_NAME                 STATUS
------------------------------ --------
PART1                          USABLE
PART2                          USABLE

Reviews    
4 stars If you have more indexes ...   April 4, 2008 - 4pm Central time zone
Reviewer: Dragos Craciun from Romania
To make all local indexes on a partition unusable:
ALTER TABLE <table_name> MODIFY PARTITION <part_name> UNUSABLE LOCAL INDEXES;

To rebuild:
ALTER TABLE <table_name> MODIFY PARTITION <part_name> REBUILD UNUSABLE LOCAL INDEXES;


5 stars   April 7, 2008 - 10am Central time zone
Reviewer: arun pradhan from Birmingham,AL
Hi Tom,
Thanks And its a great solution...I have been using temporary table and exchanging the partition till now... I beleive, making index unusable is same as having no indexes at all.
Arun Pradhan

5 stars   April 7, 2008 - 10am Central time zone
Reviewer: arun pradhan from Birmingham,AL
Hi Tom,
Thanks And its a great solution...I have been using temporary table and exchanging the partition till now... I beleive, making index unusable is same as having no indexes at all.
Arun Pradhan

5 stars Local partitions   July 23, 2009 - 10am Central time zone
Reviewer: reader from UK
This is fantastic - I never knew you could do that!

Thanks Tom


4 stars   July 30, 2009 - 2pm Central time zone
Reviewer: Sachin from USA
i tried what you said to set partition index unusable. but when i run select query optimiser won't 
consider indexes at all.


Followup   August 3, 2009 - 5pm Central time zone:

explain what you mean?

it won't use unusable indexes - this is true (new default setting:

ops$tkyte%ORA10GR2> show parameter unusable

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
skip_unusable_indexes                boolean     TRUE


it is true by default) - but so what? It isn't usable so we skip it?

If you want it to fail, unset that default setting, set it to false.
4 stars local index dropped   August 23, 2010 - 3am Central time zone
Reviewer: A reader 
Hi Tom,

I have following confusions about local indexes. It would be great if you can explain the same.

we have a range partitoned table and loacl index in the following way.
craete table tab1
(....)
partiton(...)
(.. part1..,
..part2..,
..part3..)

create index idx  ...
local
(.. part1..,
..part2..,
..part3..)

1. If we drop one partition of a table why all the local indexes(part1,part2,part3) get dropped but 
idx remains in database? I couldn't find index in dba_part_indexes view 
2. In the above case if we add a new partion how we will create indexes using idx.
3. What is the difference of creating local indexes by
create index CREATE INDEX year_idx
on all_facts (order_year)
LOCAL

and 

CREATE INDEX year_idx
on all_facts (order_year)
LOCAL
(partion_name,
....
)
Because in both the cases i found sub_objects are created as par partiton names.


Followup   August 26, 2010 - 9am Central time zone:

it does not work the way you describe:

ops$tkyte%ORA10GR2> CREATE TABLE t
  2  (
  3    dt  date,
  4    x   int,
  5    y   varchar2(30)
  6  )
  7  PARTITION BY RANGE (dt)
  8  (
  9    PARTITION part1 VALUES LESS THAN (to_date('13-mar-2003','dd-mon-yyyy')) ,
 10    PARTITION part2 VALUES LESS THAN (to_date('14-mar-2003','dd-mon-yyyy'))
 11  )
 12  /

Table created.

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> create index t_idx on t(x) local
  2  ( partition I_part1, partition I_part2 );

Index created.

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> select partition_name from user_tab_partitions where table_name = 'T';

PARTITION_NAME
------------------------------
PART1
PART2

ops$tkyte%ORA10GR2> select partition_name from user_ind_partitions where index_name = 'T_IDX';

PARTITION_NAME
------------------------------
I_PART1
I_PART2

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> alter table t drop partition part1;

Table altered.

ops$tkyte%ORA10GR2> select partition_name from user_tab_partitions where table_name = 'T';

PARTITION_NAME
------------------------------
PART2

ops$tkyte%ORA10GR2> select partition_name from user_ind_partitions where index_name = 'T_IDX';

PARTITION_NAME
------------------------------
I_PART2

that shows if you drop a table partition, only the affected index partition goes away... so that 
is counter to your #1 


ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> alter table t add partition part3 values less than 
(to_date('15-mar-2003','dd-mon-yyyy'));

Table altered.

ops$tkyte%ORA10GR2> select partition_name from user_tab_partitions where table_name = 'T';

PARTITION_NAME
------------------------------
PART3
PART2

ops$tkyte%ORA10GR2> select partition_name from user_ind_partitions where index_name = 'T_IDX';

PARTITION_NAME
------------------------------
PART3
I_PART2

that shows if you add a table partition, we automagically add the local index partition for you - 
#2 


and the difference between just "local" and "local (partition x, partition y)" is that the former local names the partitions after the table partitions (sensible) and the latter local (partition ....) lets you name the partitions differently (not as sensible in my opinion)


4 stars Partition On table.   September 2, 2010 - 11pm Central time zone
Reviewer: Snehasish Das from Kolkata , India
Hi Tom,

I was thinking if we could set the partition of the tables as unused. Suppose we have a partition 
in which we think the data is corrupted and we dont want our query to fetch data from that 
partition. Is there any way we can set the table partition to be unused. I think we can set the 
tablespace offline for that partition but that is a dba stuff. Can you tell us if it is possible 
like setting the index unused.

Regards,
Snehasish Das


Followup   September 9, 2010 - 7pm Central time zone:

create an empty table that looks like the partitioned table, create indexes on it to match the local indexes on the partitioned table, exchange that empty table with the partition you believe to be logically corrupt.

if the partition is physically corrupt, you would have to media recovery it or drop it (and then restore it later and add it back in)

you cannot "set unused" a partition, you have to remove it. setting an index unused doesn't "change the answer to queries", setting a table partition 'unused' would. therefore you need to drop it.
3 stars Index on Partition   October 7, 2011 - 4pm Central time zone
Reviewer: Ananth from Richmond VA, USA
Hi Tom,

Can i create index only on one of the partitions.
we Have 66 paritions and we dont require indexes on 65 paritions.

Is there any way to create index only on 66th partition..?

Regards
Ananth





All information and materials provided here are provided "as-is"; Oracle disclaims all express and implied warranties, including, the implied warranties of merchantability or fitness for a particular use. Oracle shall not be liable for any damages, including, direct, indirect, incidental, special or consequential damages for loss of profits, revenue, data or data use, incurred by you or any third party in connection with the use of this information or these materials.

About Oracle | Legal Notices and Terms of Use | Privacy Statement