What are Oracle Indexes?
- Just like we have index present in the textbooks to help us find
the particular topic in the book, Oracle index behaves the same way.we
have different types of indexes in oracle.
- Indexes are used to search the rows in the table quickly. If
the index is not present the select query has to read the whole table and
returns the rows. With Index, the rows can be retrieved quickly
- We should create Indexes when selecting a small percentage of rows
from a table (less than 2-4%). If the % of rows returned is high then
index scan will be slow. It also depends on the data distribution i.e
clustering factor
- Indexes are logically and physically independent of the data in the
associate table.
- Indexes are optional structures associated with tables and
clusters. You can create indexes on one or more columns of a table to
speed SQL statement execution on that table.
- Indexes are the primary means of reducing disk I/O when properly
used.
- The query decides at the beginning whether to use index or no
- The best thing with indexes is that retrieval performance of
indexed data remains almost constant, even as new rows are inserted.
However, the presence of many indexes on a table decreases the performance
of updates, deletes, and inserts because Oracle must also update the
indexes associated with the table.
- If you are owner of table, you can create index or if
you want to create index for table in another schema then you should
either have CREATE ANY INDEX system privilege or index
privilege on that table
Logical Type of Indexes
It defines the application characteristics of the Index
Unique or Non Unique
|
Index can be Unique or non Unique. Oracle create
unique index for Primary key and unique key constraints
|
Composite
|
The index can be comprised of single of multiple
columns. Composite indexes can speed retrieval of data for SELECT statement
in which the WHERE clause references all or the leading portion of the
columns in the composite index.
|
Function Based indexes
|
The indexed column’s data is based on a calculation
|
Application Domain Indexes
|
This index used in special applications (Spatial, Text).
|
What is ROWID Pseudo column
ROWID returns the address of each row in the table. Oracle
assigns a ROWID to each row.ROWID consists of following
- The data object number of the object
- The data block in the datafile in which the row resides
- The position of the row in the data block (first row is 0)
- The datafile in which the row resides (first file is 1). The file
number is relative to the tablespace.
Oracle uses ROWID internally to access rows. For instance,
Oracle stores ROWID in index and uses it to access the row in the table.
You can display ROWID of rows using SELECT command as
follows:
select rowid, emp_name from emp;
ROWID EMP_NAME
AAADC576474722aSAAA John
Oracle provides a package called DBMS_ROWID to decode
ROWID.
Once a row is assigned a ROWID Oracle does not change
ROWID during the lifetime of the row. But it changes when the table is rebuild.
Types of indexes in oracle with example
There are 6 different types of indexes in oracle
1) B-Tree
2) Compressed B-Tree
3) Bitmap
4) Function-Based
5) Reverse Key (RKI)
6) Index organized table (IOT).
B – Tree Index:
- B-Tree Indexes (balanced tree) are the most common type of index.
- B-Tree index stored the ROWID and the index key value in a tree
structure.
- When creating an index, a ROOT block is created, then BRANCH blocks
are created and finally LEAF blocks.
- Each branch holds the range of data its leaf blocks hold, and each
root holds the range of data its branches hold:
- B-Tree indexes are most useful on columns that appear in the where
clause (SELECT … WHERE EMPNO=1).
- The Oracle server, keeps the tree balanced by splitting index
blocks, when new data is inserted to the table.
- Whenever a DML statement is performed on the index’s table, index
activity occurs, making the index to grow (add leaf and branches).
Advantages
- All leaf blocks of the tree are at the same depth.
- B-tree indexes automatically stay balanced.
- All blocks of the B-tree are three-quarters full on the average.
- B-trees provide excellent retrieval performance for a wide range of
queries, including exact match and range searches.
- Inserts, updates, and deletes are efficient, maintaining key order
for fast retrieval.
- B-tree performance is good for both small and large tables, and
does not degrade as the size of a table grows.
CREATE <UNIQUE|NON UNIQUE> INDEX
<index_name>
ON
<table_name> (<column_name>,<column_name>…)
TABLESPACE
<tablespace_name>;
Example
Create
index scott.exp_idx on table scott.example(
name)
Tablespace
TOOLS;
|
What is compressed B-tree Indexes
Compressed B-Tree Indexes are built on large tables, in a
data warehouse environment. In this type of index, duplicate occurrences of the
same value are eliminated, thus reducing the amount of storage space, the index
requires. In a compressed B-Tree index, for each key value, a list of ROWIDs
are kept:
Specifying the COMPRESS keyword when creating an index
(CREATE INDEX … COMPRESS) will create a compressed B-Tree index. A regular
B-Tree index can be rebuilt using the COMPRESS keyword to compress it.
CREATE <UNIQUE|NON UNIQUE> INDEX
<index_name>
ON
<table_name> (<column_name>,<column_name>…)
PCTFREE
<integer>
TABLESPACE
<tablespace_name>
Compress
<column number>;
|
What is Bitmap Indexes
Bitmap Indexes are most appropriate on low distinct
cardinality data (as opposed to B-Tree indexes).
This type of index, creates a binary map of all index
values, and store that map in the index blocks, this means that the index will
require less space than B-Tree index.
Each bit in the bitmap corresponds to a possible rowid. If the bit is set, then
it means that the row with the corresponding rowid contains the key value. A
mapping function converts the bit position to an actual rowid, so the bitmap
index provides the same functionality as a regular index even though it uses a
different representation internally. If the number of different key values is
small, then bitmap indexes are very space efficient
The Bitmap index is useful on large columns with low-DML
activity like marital status (M/S) or gender (M/F).
Bitmap Index structure contain a map of bits which
indicate the value in the column, for example, for the GENDER column, the index
block will hold the starting ROWID, the ending ROWID and the bit map:
Bitmap indexes are very useful when created on columns
with low cardinality, used with the AND & OR operator in the query
condition:
CREATE BITMAP INDEX <index_name>
ON
<table_name> (<column_name>,<column_name>…)
PCTFREE
<integer>
TABLESPACE
<tablespace_name>;
|
Example
CREATE BITMAP INDEX ON emp_data(gender);
SELECT
COUNT(*) FROM emp_data
WHERE
GENDER=’M”;
|
Advantages Of Bitmap Indexes
- Reduced response time for large classes of queries
- A substantial reduction of space usage compared to other indexing
techniques
- Dramatic performance gains even on very low end hardware
- Very efficient parallel DML and loads
Function Based Indexes
Function-Based Indexes are indexes created on columns that
a function is usually applied on.
When using a function on an indexed column, the index is
ignored, therefore a function-based index is very useful for these operations.
CREATE INDEX <index_name>
ON
<table_name> [ Function(<column_name>,<column_name.)]
TABLESPACE
<tablespace_name>;
Example
CREATE
INDEX EMP_IDX on EMP(UPPER(ENAME));
SELECT
*
FROM
Emp
WHERE
UPPER(Ename) like ‘JOHN`;
|
What is Reverse-Key Indexes
They are special types of B-Tree indexes and are
very useful when created on columns contain sequential numbers.
When using a regular B-Tree, the index will grow to have
many branches and perhaps several levels, thus causing performance degradation,
the RKI solve the problem by reversing the bytes of each column key and
indexing the new data.
This method distributes the data evenly in the index. Creating a RKI is done
using the REVERSE keyword: CREATE INDEX … ON … REVERSE;
CREATE INDEX <index_name>
ON
<table_name> (<column_name>)
TABLESPACE
<tablespace_name>
REVERSE;
Example
CREATE
INDEX emp_idx i ON emp_table (firstname,lastname) REVERSE;
|
What is Index Organized Tables (IOT) –
When we are using B-Tree, Bitmap and Reverse key
indexes are used for tables that store data in an unordered fashion (Heap
Tables).
These indexes contain the location of the ROWID of
required table row, thus allowing direct access to row data
An index-organized
table differs from an ordinary table because the data for the
table is held in its associated index. Changes to the table data, such as
adding new rows, updating rows, or deleting rows, result in updating the index.
The index-organized table is like an ordinary table with
an index on one or more of its columns, but instead of maintaining two separate
storages for the table and the B-tree index, the database system maintains only
a single B-tree index which contains both the encoded key value and the
associated column values for the corresponding row. Rather than having a row’s
rowid as the second element of the index entry, the actual data row is stored
in the B-tree index. The data rows are built on the primary key for the table,
and each B-tree index entry contains <primary_key_value,
non_primary_key_column_values>. Index-organized tables are suitable for
accessing data by the primary key or any key that is a valid prefix of the
primary key.
There is no duplication of key values because only non-key column values are
stored with the key. You can build secondary indexes to provide efficient
access by other columns. Applications manipulate the index-organized table just
like an ordinary table, using SQL statements. However, the database system
performs all operations by manipulating the corresponding B-tree index.
Features
of Index organized table
Primary key uniquely identifies a row; primary key must be
specified
Primary key based access
Logical rowid in ROWID pseudocolumn allows building
secondary indexes
UNIQUE constraint not allowed but triggers are allowed
Cannot be stored in a cluster
Can contain LOB columns but not LONG columns
Distribution and replication not supported
There are 2 benefits of using IOT: 1. table rows are
indexes, access to table is done using its primary key, the row is returned
quickly from IOT than heap tables. 2.
CREATE TABLE command:
CREATE
TABLE …
ORGANIZATION
INDEX TABLESPACE … (specify this is an IOT)
PCTTHRESHOLD
… (specify % of block to hold in order to store row data, valid 0-50 (default
50))
INCLUDING
… (specify which column to break a row when row length exceeds PCTTHRESHOLD)
OVERFLOW TABLESPACE … (specify the tablespace where the second part of the row
will be stored) MAPPING TABLE; (cause creation of a mapping table, needed
when creating Bitmap index on IOT)
|
The Mapping Table maps the index’s physical ROWIDs
to logical ROWIDs in the IOT. IOT use logical ROWIDs to manage table access by
index because physical ROWIDs are changed whenever data is added to or removed
from the table. In order to distinct the IOT from other indexes, query the
USER_INDEXES view using the pct_direct_access column. Only IOT will have a
non-NULL value for this column.
Application Domain Indexes
Oracle provides extensible
indexing to accommodate indexes on complex data types such as
documents, spatial data, images, and video clips and to make use of specialized
indexing techniques.
With extensible indexing, you can encapsulate
application-specific index management routines as an indextype schema
object and define a domain index (an
application-specific index) on table columns or attributes of an object type.
Extensible indexing also provides efficient processing of application-specific operators.
The application software, called the cartridge,
controls the structure and content of a domain index. The Oracle server
interacts with the application to build, maintain, and search the domain index.
The index structure itself can be stored in the Oracle database as an
index-organized table or externally as a file.
Using Domain Indexes
Domain indexes are built using the indexing logic supplied
by a user-defined indextype. An indextype provides an efficient mechanism to
access data that satisfy certain operator predicates. Typically, the user-defined
indextype is part of an Oracle option, like the Spatial option.
For example, the SpatialIndextype allows efficient search
and retrieval of spatial data that overlap a given bounding box.
The cartridge determines the parameters you can specify in
creating and maintaining the domain index. Similarly, the performance and
storage characteristics of the domain index are presented in the specific
cartridge documentation.
So far we have covered different types of indexes in
oracle with example,lets now check how to alter/drop/recreate them
How to recreate the Indexes/rebuild index in oracle
We can Use the ALTER INDEX … REBUILD statement to
reorganize or compact an existing index or to change its storage
characteristics
The REBUILD statement uses the existing index as the basis
for the new one.
ALTER INDEX … REBUILD is usually faster than dropping and
re-creating an index.
It reads all the index blocks using multiblock I/O then
discards the branch blocks.
A further advantage of this approach is that the old index
is still available for queries while the rebuild is in progress.
Alter index <index name> rebuild ;
Alter
index <index name> rebuild tablespace <name>;
|
How to Write Statements that Avoid Using Indexes
- You can use the NO_INDEX hint to give the CBO maximum flexibility
while disallowing the use of a certain index.
- You can use the FULL hint to force the optimizer to choose a full
table scan instead of an index scan.
- You can use the INDEX, INDEX_COMBINE, or AND_EQUAL hints to force the optimizer to use one index or a set of listed indexes instead of another.
How to gather statistics for Indexes
Index statistics are gathered using the ANALYZE INDEX or
dbms_stats statement.
Available options are COMPUTE/ESTIMATE STATISTICS or
VALIDATE STRUCTURE.
With 10g onwards, when the index is created, compute
statistics is done automatically
When using the validate structure, Oracle populates the
INDEX_STATS view with statistics related to analyzed index. The statistics
contain number of leaf rows & blocks (LF_ROWS, LF_BLKS), number branch rows
& blocks (BR_ROWS, BR_BLKS), number of deleted leaf rows (DEL_LF_ROWS),
used space (USED_SPACE), number of distinct keys (DISTINCT_KEYS) etc. These
statistics can be used to determine if the index should be rebuild or not
How does Oracle decide about the usage of index?
Oracle automatically decides about whether index should be
used by Optimizer engine.
Oracle decides whether to use an index or not depending
upon the query.
Oracle can understand whether using an index will improve
the performance in the given query. If Oracle thinks using an index will
improve performance, it will use the index otherwise it will ignore the index.
Let us understand by this example
We have a table emp which contains emp_name,
salary,dept_no ,emp_no,date_of_joining and we have an index on emp_name
Query 1
select * from emp where emp_name = ‘John’;
The above query will use the index as we are trying to get
information about a emp based on the name.
Query 2
select * from emp;
The above query will not use index as we are trying to
find all the rows in the table and we don’t have where clause in the
query
Query 3
select * from emp where dept_no =5;
The above query will not use index as the where clause
does not select the column which has index
Query 4
select * from emp where substr(emp_name,1,4) =’XYZW’;
The above query will not use index as the where clause
uses the function on the column and we don’t have functional index on emp_name
How to create or rebuild the index Online?
Oracle used to lock the table on which index is being
created throughout creation process in older vesions.This makes table
unavailable for data manipulation during the creation of index.
Now with 8i , Oracle introduced online rebuilding of
index where Oracle doesn’t lock the table on which index is being built.
Online indexing is provided through the keyword ONLINE.
CREATE <UNIQUE|NON UNIQUE> INDEX
<index_name>
ON
<table_name> (<column_name>,<column_name>…)
PCTFREE
<integer>
TABLESPACE
<tablespace_name>
Online;
Alter
index <index name> rebuild online;
|
Basically with online rebuild,Oracle locks the table at
the start and end of the creation of the index. It allows transaction in
between. The mechanism has been quite improved with 11g and 12c
What are the Drawbacks of the Indexes
Indexes increase performance of select query, they
can also decrease performance of data manipulation.
Many indexes on a table can slow down INSERTS and DELETES
drastically
The more the indexes on the table, the more time inserts
and delete will take.
Similarly every change to an indexed column will need a
change to index.
So we need to choose the index very carefully and drop
which are not in use.
Though the extra space occupied by indexes is also a
consideration, it may not matter much since the cost of data storage has declined
substantially.
How to Drop the index in Oracle
You can drop an index using DROP INDEX command.
It removes the named index.
You should be carefully while dropping the index as we may
leads to bad performance in queries where it is used.
drop index <index name> ;
|
What is Unusable indexes
An unusable index is ignored by the optimizer in deciding
the explain plan
It is also not maintained by DML i.e update,insert,
delete does the update the index
There could be several for index in unusable state.
You did the rebuild of the table but did not rebuild the index, then index will
be unusable state. One other reason to make an index unusable is to
improve bulk load performance. Another reason might be optimizer picking up the
wrong index everytime and time is critical so you may decide to make it
unusable
An unusable index or index partition must be rebuilt, or
dropped and re-created, before it can be used. Truncating a table makes an
unusable index valid.
Beginning with Oracle Database 11g Release 2, when you
make an existing index unusable, its index segment is dropped.
The functionality of unusable indexes depends on the
setting of the SKIP_UNUSABLE_INDEXES initialization parameter.
When SKIP_UNUSABLE_INDEXES is TRUE (the default), then:
DML statements against the table proceed, but unusable
indexes are not maintained.
DML statements terminate with an error if there are any
unusable indexes that are used to enforce the UNIQUE constraint.
For nonpartitioned indexes, the optimizer does not
consider any unusable indexes when creating an access plan for SELECT
statements. The only exception is when an index is explicitly specified with
the INDEX() hint.
When SKIP_UNUSABLE_INDEXES is FALSE, then:
If any unusable indexes or index partitions are present,
any DML statements that would cause those indexes or index partitions to be
updated are terminated with an error.
For SELECT statements, if an unusable index or unusable
index partition is present but the optimizer does not choose to use it for the
access plan, the statement proceeds. However, if the optimizer does choose to
use the unusable index or unusable index partition, the statement terminates
with an error.
What are Invisible Indexes?
Beginning with Oracle Database 11g Release 1, you can
create invisible indexes or make an existing index invisible. An invisible
index is ignored by the optimizer unless you explicitly set the
OPTIMIZER_USE_INVISIBLE_INDEXES initialization parameter to TRUE at the session
or system level. Unlike unusable indexes, an invisible index is maintained
during DML statements. Although you can make a partitioned index invisible, you
cannot make an individual index partition invisible while leaving the other partitions
visible. Using invisible indexes, you can do the following:
- Test the removal of an index before dropping it.
- Use temporary index structures for certain operations or modules of an application without affecting the overall application.
Data dictionary views on Indexes
DBA_INDEXES
ALL_INDEXES
USER_INDEXES
|
DBA view describes indexes on all tables in the
database. ALL view describes indexes on all tables accessible to the user.
USER view is restricted to indexes owned by the user. Some columns in these
views contain statistics that are generated by the DBMS_STATS package or
ANALYZE statement.
|
DBA_IND_COLUMNS
ALL_IND_COLUMNS
USER_IND_COLUMNS
|
These views describe the columns of indexes on tables.
Some columns in these views contain statistics that are generated by the
DBMS_STATS package or ANALYZE statement.
|
DBA_IND_EXPRESSIONS
ALL_IND_EXPRESSIONS
USER_IND_EXPRESSIONS
|
These views describe the expressions of function-based
indexes on tables.
|
DBA_IND_STATISTICS
ALL_IND_STATISTICS
USER_IND_STATISTICS
|
These views contain optimizer statistics for indexes.
|
how to find indexes on a table in oracle
set pagesize 50000 verify off echo off
col
table_name head ‘Table Name’ format a20
col
index_name head ‘Index Name’ format a25
col
column_name head ‘Column Name’ format a30
break
on table_name on index_name
select
table_name, index_name, column_name
from
all_ind_columns
where
table_name like upper(‘&Table_Name’)
order
by table_name, index_name, column_position
/
|
How to determine index size
Size of INDEX
select
segment_name,sum(bytes)/1024/1024/1024 as “SIZE in GB” from user_segments
where segment_name=’INDEX_NAME’ group by segment_name;
OR
select
owner,segment_name,sum(bytes)/1024/1024/1024 as “SIZE in GB” from
dba_segments where owner=’SCHEMA_NAME’ and segment_name=’INDEX_NAME’ group by
owner,segment_name;
List of Size of all
INDEXES of a USER
select
segment_name,sum(bytes)/1024/1024/1024 as “SIZE in GB” from user_segments
where segment_type=’INDEX’ group by segment_name order by “SIZE in GB” desc;
OR
select
owner,segment_name,sum(bytes)/1024/1024/1024 as “SIZE in GB” from
dba_segments where owner=’SCHEMA_NAME’ and segment_type=’INDEX’ group by
owner,segment_name order by “SIZE in GB” desc;
Sum of sizes of all
indexes
select
owner,sum(bytes)/1024/1024/1024 as “SIZE in GB” from dba_segments where
owner=’SCHEMA_NAME’ and segment_type=’INDEX’ group by owner;
|
How to determine the Index defination
set long 4000
select dbms_metadata.get_ddl(‘INDEX’,'<INDEX
Name>’,'<INDEX OWNER’) from dual;
How to determine the Index statistics
set pages 250
set linesize 100
set verify off
col table_name format a24 heading ‘TABLE NAME’
col index_name format a23 heading ‘INDEX NAME’
col u format a1 heading ‘U’
col blevel format 0 heading ‘BL’
col leaf_blocks format 999990 heading ‘LEAF|BLOCKS’
col distinct_keys format 9999990 heading ‘DISTINCT|KEYS’
col avg_leaf_blocks_per_key format 9999990 heading ‘LEAF|BLKS|/KEY’
col avg_data_blocks_per_key format 9999990 heading ‘DATA|BLKS|/KEY’
rem
break on table_name
rem
select table_name, index_name,
decode( uniqueness, ‘UNIQUE’, ‘U’, null ) u,
blevel, leaf_blocks, distinct_keys,
avg_leaf_blocks_per_key, avg_data_blocks_per_key
from sys.dba_indexes
where table_owner like upper(‘&owner’)
and table_name like upper(‘&table’)
order by table_owner, table_name, index_name;
set linesize 100
set verify off
col table_name format a24 heading ‘TABLE NAME’
col index_name format a23 heading ‘INDEX NAME’
col u format a1 heading ‘U’
col blevel format 0 heading ‘BL’
col leaf_blocks format 999990 heading ‘LEAF|BLOCKS’
col distinct_keys format 9999990 heading ‘DISTINCT|KEYS’
col avg_leaf_blocks_per_key format 9999990 heading ‘LEAF|BLKS|/KEY’
col avg_data_blocks_per_key format 9999990 heading ‘DATA|BLKS|/KEY’
rem
break on table_name
rem
select table_name, index_name,
decode( uniqueness, ‘UNIQUE’, ‘U’, null ) u,
blevel, leaf_blocks, distinct_keys,
avg_leaf_blocks_per_key, avg_data_blocks_per_key
from sys.dba_indexes
where table_owner like upper(‘&owner’)
and table_name like upper(‘&table’)
order by table_owner, table_name, index_name;
Comments
Post a Comment