Select all indexes by status

Check indexes by status by two queries from metadata of Oracle. Depending on your needs and rights you can use them:

  • all_indexes - this will group and count all indexes by status
  • user_objects - this will show you all indexes and their information. You can filter by status.
  • dba_indexes - third query is preparing script for dropping all indexes for a particular owner
--select all indexes grouped by status
SELECT 
 status, 
COUNT(*) 
FROM   all_indexes 
GROUP BY status

--view all invalid indexes
select * 
from user_objects
where object_type = 'INDEX'
and status ='INVALID'--and status ='VALID' 

--prepared script for dropping all indexes for MYOWNER
SELECT 'drop index MYOWNER.' || index_name || ';'
FROM dba_indexes
WHERE table_owner = 'MYOWNER';

Index rebuild

In oracle indexes rebuilding is fairly an easy operation. It depends on the type of the index:

  • normal index rebuild
alter index index_name rebuild;
  • normal index rebuild has this syntax:
alter index <index_name> rebuild partition <partition_name>;

Information about the partition can be taken from the table DDL using tools like SQL Developer.

alter index index_name rebuild partition partition1;
alter index index_name rebuild partition partition2;
alter index index_name rebuild partition partition3;
...
alter index index_name rebuild partition partition64;

Script collecting all needed subpartitions

SELECT 'ALTER INDEX '||index_owner||'.'|| INDEX_NAME ||' rebuild SUBPARTITION ' || SUBPARTITION_NAME ||'  ONLINE PARALLEL;'
FROM dba_ind_subpartitions
WHERE INDEX_NAME = 'INDEX_NAME';

Script collecting all needed partitions

SELECT 'ALTER INDEX '||'MYOWNER'||'.'|| 'INDEX_NAME' ||' rebuild PARTITION ' || PARTITION_NAME ||'  ONLINE PARALLEL;'  
FROM all_ind_partitions  
WHERE INDEX_NAME = 'INDEX_NAME'
and INDEX_OWNER = 'MYOWNER'; 

SELECT 'ALTER INDEX '||'MYOWNER'||'.'|| 'INDEX_NAME' ||' rebuild PARTITION ' || PARTITION_NAME ||'  ONLINE PARALLEL;'  
FROM dba_ind_partitions  
WHERE INDEX_NAME = 'INDEX_NAME'

Alter Index Offline

In oracle you may need to make the index unusable or to drop it prior to rebuild it:

  • make index unusable
alter index index_name unusable;
  • drop index
drop index index_name

Create index

After dropping an index or if you need a new one you can create it by:

-- create unique index
CREATE  UNIQUE INDEX INDEX_NAME ON "TABLE" ("COLUMN")  ONLINE;

-- create online index 
CREATE  INDEX "INDEX_NAME" ON "TABLE" ("COLUMN", "COLUMN2")  ONLINE;

--create index parallel 
create index "MYOWNER"."MYTABLE$IND" on "MYOWNER"."MYTABLE" (column1,column2,column3) tablespace ts_indexes local parallel 12 online;


--create partioned global
create index "MYOWNER"."MYTABLE$IND" on "MYOWNER"."MYTABLE"  (column_date) global;

--create partioned local
create index "MYOWNER"."MYTABLE$IND" on "MYOWNER"."MYTABLE"  (column_date) local;

--create partion index by hash
CREATE INDEX INDEX_NAME ON "MYOWNER"."MYTABLE" (column1,column2,column3) GLOBAL
     PARTITION BY HASH (column1,column2)
     (PARTITION p1  TABLESPACE tbs_1,
      PARTITION p2  TABLESPACE tbs_2,
      PARTITION p3  TABLESPACE tbs_3,
      PARTITION p4  TABLESPACE tbs_4);
      
      
--create index by range
CREATE INDEX "MYOWNER"."MYTABLE$IND" ON "MYOWNER"."MYTABLE" ("COLUMN1","COLUMN1") 
GLOBAL PARTITION by range (COLUMN1)
    (
    PARTITION r1 VALUES LESS THAN (TO_DATE('1-JAN-1999','DD-MON-YYYY')),
    PARTITION r2 VALUES LESS THAN (TO_DATE('1-JAN-2000','DD-MON-YYYY')),
    PARTITION r3 VALUES LESS THAN (TO_DATE('1-JAN-2001','DD-MON-YYYY')),
    ...
    );

Check index usage

Explain plan

If you wonder whether the index is used and what is the performance you can check execute plan for a given query by :

explain plan for select * from mytable;
select * from table(dbms_xplan.display);
  • Run first query and replace select * from mytable with your query
  • wait for explained to be shown
  • run select * from table(dbms_xplan.display); in order to get the result
  • result would be something like:
--------------------------------------------------------------------
| Id  | Operation            |  Name       | Rows  | Bytes | Cost  |
--------------------------------------------------------------------
|   0 | SELECT STATEMENT     |             |    111|    444|     5 |
|   1 |  TABLE ACCESS FULL   | MYTABLE     |    111|    444|     5 |

SQL Tunning Advisor

You can use also SQL Tunning Advisor which is available after version 3.0 of SQL Developer(it requires also Oracle Database 11g Enterprise Edition with access to the Tuning and Diagnostic management packs and with the sample schema installed). It can be executed by F10 while you selected your query or by right click on it and select SQL Tunning Advisor.

It will give you information for the several execution plans, recommendations for new indexes or query enhancements:

  • findings on SQL profiles
  • gathering statistics
  • useful indexes
  • rewrites query

The output would be:

GENERAL INFORMATION SECTION
-------------------------------------------------------------------------------
Tuning Task Name   : 11111
Tuning Task Owner  : MyOwner
Workload Type      : Single SQL Statement


-------------------------------------------------------------------------------

-------------------------------------------------------------------------------
FINDINGS SECTION (2 findings)
-------------------------------------------------------------------------------

1- SQL Profile Finding (see explain plans section below)
--------------------------------------------------------

2- Index Finding (see explain plans section below)
--------------------------------------------------

-------------------------------------------------------------------------------
EXPLAIN PLANS SECTION
-------------------------------------------------------------------------------

1- Original
-----------

2- Original With Adjusted Cost
------------------------------

3- Using New Indices
--------------------

4- Using SQL Profile
--------------------

Errors related to indexes

For some queries on Oracle tables with select SQL statement, Oracle can return the following error:

ORA-01502: index ‘string.string’ or partition of such index is in unusable state

The error indicates 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.

The solution would be:

1.Drop the specified index and/or recreate the index
2.Rebuild the specified index
3.Rebuild the unusable index partition

Generally, the following SQL manipulation language will be enough to rebuild the unusable index:

  • index rebuild
ALTER INDEX index_name REBUILD