Vous êtes sur la page 1sur 10

Goal of an index is to speed the process of finding data.

An index file contains a data


value for a specific field in a table and a pointer that identifies the record that contains a
value for that field. In other words, an index on the last_name field for a table would
contain a list of last names and pointers to specific records—just as an index to a book
lists topics and page numbers to enable readers to access information quickly. When
processing a request, the database optimizer will choose some or all of the available
indexes to efficiently locate the requested rows.

How Indexes become fragmented

The advantages of indexing do not come without a cost. As database objects, indexes are
created for tables only and they must be in sync with them: indexes must be updated by the
database with every data manipulation language (DML) operation—INSERT, DELETE, or
UPDATE. When a row is deleted from a table, the Oracle database will not reuse the
corresponding index space until you rebuild the index. That's the way indexes are implemented in
Oracle. The PCTUSED parameter for indexes is always 0, which means that—unlike table blocks
—index blocks will not be put on the free list for reuse.

Therefore, indexes are always growing and can become very fragmented over time, especially in
tables with dynamic data. As indexes grow, two things happen: splitting and spawning.

Splitting happens when an index node becomes full with keys and a new index node is created at
the same level as a full node. This widens the B*-tree horizontally and may degrade performance

Spawning is the process of adding a new level to an index. As a new index is populated, it begins
life as a single-level index. As keys are added, a spawning takes place and the first-level node
reconfigures itself to have pointers to lower-level nodes

Index Usage:
Sometimes an index needs to be monitored and see if it is used or not.
This information is very helpful in deciding if the indexes, which exist in the database, can be
dropped or not.
The index monitoring can be done using
ALTER INDEX index_name MONITORING USAGE for starting to monitor the index and ALTER
INDEX index_name NOMONITORING USAGE to stop monitoring the index.
The V$OBJECT_USAGE view provide the result if that specific index is used or not by the CBO
(Cost Based Optimizer).

The "USED" column in V$OBJECT_USAGE is changed to YES by the optimizer if the index is
being used in an access path.

alter index index_name monitoring usage;

Select index_name,monitoring,used,start_monitoring,end_monitoring from


v$object_usage;

When to Rebuild Indexes

The only time you need to rebuild indexes is when the cost to rebuild is less that the
performance gained. The first one is obvious. Pack your tables and indexes (rebuild into
the soon to be read-only tablespace) tightly and they will stay that way. The second is
much more difficult. First, it is a continuing process since the index will move toward
fluff with use. Second, there is the cost of rebuilding the index AND the cost of the
additional redo as the index changes. There is only one method to determine is rebuilding
an indexes benefits your database, testing.
Detecting Most used Index(s) and Index table(s):

The problem has always been that it is very difficult to know what indexes are the most
popular. In Oracle10g we can easily see what indexes are used, when they are used and
the context where they are used. Here is a simple AWR query to plot index usage:

select
p.object_name i_name,
p.operation Operation,
p.options Options,
P.OBJECT_OWNER,
count(1) i_usage
from
dba_hist_sql_plan p,
dba_hist_sqlstat s
where
p.object_owner <> 'SYS'
and
p.object_owner <> 'SYSTEM'
and
p.object_owner <> 'SYSMAN'
and
p.operation like '%INDEX%'
and
p.object_owner <> 'XDB'
and
p.sql_id = s.sql_id
group by
p.object_name,
p.operation,
p.options,
p.object_owner
order by
1,2,3 desc;

Gets per index access

The number of "gets" per access refers to the amount of logical I/O that is required to
fetch a row with the index. As you may know, a logical "get" is not necessarily a physical
I/O since much of the index may reside in the Oracle buffer cache. However, any SAP
index with a number greater than 10 would probably benefit from an index rebuild.

Unfortunately, Oracle does not make it easy to capture this information. In Oracle we
must issue these commands:
ANALYZE INDEX index_name COMPUTE STATISTICS
ANALYZE INDEX index_name VALIDATE STRUCTURE

After you analyze the report above, you may want to consider rebuilding any index where
the height is more than three levels, since three levels will support millions of index
entries. Note that Oracle indexes will “spawn” to a fourth level only in areas of the index
where a massive insert has occurred, such that 99% of the index has three levels, but the
index is reported as having four levels.

Oracle indexes are not self-balancing and proposed a method for detecting when an index
needs rebuilding. Oracle b-tree indexes become out of balance via high DML and they
have lower performance:

"Oracle indexes are not self-balancing. They become fragmented after a large number of
INSERTs and DELETEs, which may lead to significant performance degradation. This
Solution below show you how to detect these "out-of-shape" indexes and cure them.

These statistics are relevant to the index rebuilding decision:

The following INDEX_STATS columns are especially useful:

• height refers to the maximum number of levels encountered within the index. An
index could have 90 percent of the nodes at three levels, but excessive splitting
and spawning in one area of the index with heavy DML operations could make
nodes in that area to have more than three levels.

• lf_rows refers to the total number of leafs nodes in the index.

• del_lf_rows refers to the number of leaf rows that have been marked deleted as a
result of table DELETEs."

In other words, massive DELETEs seemed to damage certain index areas, but leave other
areas intact.

ANALYZE INDEX CRS.PK_FROM10 COMPUTE STATISTICS;

ANALYZE INDEX CRS.PK_FROM10 VALIDATE STRUCTURE ;

INDEX_STATS stores information from the last ANALYZE INDEX ... VALIDATE
STRUCTURE statement.
Column Datatype NULL Description
HEIGHT NUMBER Height of the B-Tree
BLOCKS NUMBER NOT Blocks allocated to the segment
NULL
NAME VARCHAR2(30) NOT Name of the index
NULL
PARTITION_NAME VARCHAR2(30) Name of the partition of the index
which was analyzed. If the index is not
partitioned, null is returned.
LF_ROWS NUMBER Number of leaf rows (values in the
index)
LF_BLKS NUMBER Number of leaf blocks in the B-Tree
LF_ROWS_LEN NUMBER Sum of the lengths of all the leaf rows
LF_BLK_LEN NUMBER Usable space in a leaf block
BR_ROWS NUMBER Number of branch rows in the B-Tree
BR_BLKS NUMBER Number of branch blocks in the B-Tree
BR_ROWS_LEN NUMBER Sum of the lengths of all the branch
blocks in the B-Tree
BR_BLK_LEN NUMBER Usable space in a branch block
DEL_LF_ROWS NUMBER Number of deleted leaf rows in the
index
DEL_LF_ROWS_LEN NUMBER Total length of all deleted rows in the
index
DISTINCT_KEYS NUMBER Number of distinct keys in the index
(may include rows that have been
deleted)
MOST_REPEATED_KEY NUMBER How many times the most repeated key
is repeated (may include rows that have
been deleted)
BTREE_SPACE NUMBER Total space currently allocated in the
B-Tree
USED_SPACE NUMBER Total space that is currently being used
in the B-Tree
PCT_USED NUMBER Percent of space allocated in the B-Tree
that is being used
ROWS_PER_KEY NUMBER Average number of rows per distinct
Column Datatype NULL Description
key (this figure is calculated without
consideration of deleted rows)
BLKS_GETS_PER_ACCESS NUMBER Expected number of consistent mode
block reads per row, assuming that a
randomly chosen row is accessed using
the index. Used to calculate the number
of consistent reads that will occur
during an index scan.
PRE_ROWS NUMBER Number of prefix rows (values in the
index)
PRE_ROWS_LEN NUMBER Sum of lengths of all prefix rows
OPT_CMPR_COUNT NUMBER Optimal key compression length
OPT_CMPR_PCTSAVE NUMBER Corresponding space savings after an
ANALYZE

select name as IndexName,


height,
lf_rows,
del_lf_rows
from index_stats;

The first rule is that an index with a height greater than 3 is a good candidate for rebuilding; tables
with height 4 and higher may lead to unnecessary index block reads, and therefore could benefit
from rebuilding.

The second rule is that the deleted leaf rows amount (del_lf_rows) should be less than 20 percent
of total number of leaf rows (lf_rows). A high number of deleted leaf rows shows that the table
has been subjected to heavy DELETE activity. As a result, the index tree becomes unbalanced
and the index is a good candidate for rebuilding.

For example, del_lf_rows equals 2130, lf_rows equals 5237; the ratio is:

(2130*100) / 5237 = 40.7 percent

Drill deeper:

That is one way of looking at index(s) efficient use, But for rebuilt we need to drill down further.

Oracle B-tree index


Normally, these indexes attempt to manage themselves internally to ensure fast access to
the data rows. However, excessive activity within a table can cause Oracle indexes to
dynamically reconfigure themselves. This reconfiguration involves three activities:

•  Index splittingThis is when the addition of new table rows cause new index
nodes to be created at existing levels

•  Index spawningAt some point, the Oracle indexes will reach the maximum
capacity for the level and the Oracle index will spawn, creating a deeper level
structure

• Index node  deletionAs you may know, Oracle index nodes are not physically
deleted when table rows are deleted, nor are the entries removed from the index.
Rather, Oracle “logically” deletes the index entry and leaves “dead” nodes in the
index tree.

One vexing issue with Oracle indexes is that the information for an index rebuild must be
gathered from two sources:

The Oracle analyze index compute statistics command

The Oracle analyze index validate structure command

Once we gather information from these sources, we can generate a report with everything
we need to know about the index internal structure i.e.

select distinct
name indx_name,
height height,
lf_rows leaf_rows,
del_lf_Rows del_leaf_rows,
most_repeated_key most_rep_keys,
distinct_keys dist_keys,
blks_gets_per_access blk_gets_per_acess
from index_stats
where
height > 3
or
del_lf_rows > 10 order by name;

From this report, we see several important statistics:

•  The number of deleted leaf nodesThe term “deleted leaf node” refers to the
number of index nodes that have been logically deleted as a result of row delete
operations. Remember that Oracle leaves “dead” index nodes in the index when
rows are deleted. This is done to speed up SQL deletes, since Oracle does not
have to rebalance the index tree when rows are deleted.
•  Index heightThe height of the index refers to the number of levels that are
spawned by the index as a result in row inserts. When a large number of rows are
added to a table, Oracle may spawn additional levels of an index to accommodate
the new rows. Hence, an Oracle index may have four levels, but only in those
areas of the index tree where the massive inserts have occurred. Oracle indexes
can support many millions of entries in three levels, and any Oracle index that has
four or more levels would benefit from rebuilding.
•  Gets per index accessThe number of “gets” per access refers to the amount of
logical I/O that is required to fetch a row with the index. As you may know, a
logical get is not necessarily a physical I/O since much of the index may reside in
the Oracle buffer cache. However, any Oracle index with a number greater than
10 would probably benefit from an index rebuild.

IMPORTANT:

We might want to rebuild an index if the block gets per access is greater than 5, since
excessive block gets indicate a fragmented B-tree structure. Another rebuild condition
would be cases where deleted leaf nodes comprise more than 20 percent of the index
nodes. Another reason to rebuild is when any index shows a depth of 4 or greater.

- deleted entries represent 20% or more of the current entries.


- the index depth is more then 4 levels.

Metalink: Index Rebuild, the Need vs the Implications [ID 989093.1]

Another source of finding index candidates

Advisor Central >> Segment Advisor

The Oracle segment advisor is one way to identify candidates for an index rebuild.

“The page lists all the segments (table, index, and so on) that constitute the object under
review.

The default view ("View Segments Recommended to Shrink") lists any segments that
have free space you can reclaim.”

Select Schema Segment Recommendation Reclaimable Space (MB) Allocated Used Segment
Space Space
Type
(MB) (MB)
CRS IDX_USERID_LOGINHISTORY 160.55 187.75 27.20 INDEX

Similarly

Allocated Used
Schema Segment
Segment Recommendation Reclaimable Space (MB) Space Space
Type
Select (MB) (MB)
IIRS IXIRRD_CLRD 10.55 35.69 25.14 INDEX
IIRS IXIRRD_GNRD 10.04 32.62 22.58 INDEX

Also Schedule a segment space advisory job for all the most-hot-index(s).

INDEX scans:

In addition to these index structures we also see interesting use of indexes at runtime.
Here is a sample of index-based access plans:

• Nested loop joins – This row access method scans an index to collect a series of
ROWID’s.

• Index fast-full-scans – This is a “multi-block read” access where the index blocks
are accessed via a “db file scattered read” to load index blocks into the buffers.
Please note that this method does not read the index nodes.

• Star joins – The star index has changed in structure several times, originally being
a single-concatenated index and then changing to a bitmap index implementation.
STAR indexes are super-fast when joining large read-only data warehouse tables.

• Index combine access – This is an example of the use of the index_combine hint.
This execution plan combines bitmap indexes to quickly resolve a low-cardinality
Boolean expression:

Another way of checking Index health:

But to run the script below you need to provide your index health threshold.
SELECT
INDEX_NAME, NUM_ROWS, ROWLEN, LEAVES, NET_MB, GROSS_MB, QUALITY
FROM
( SELECT I.INDEX_NAME INDEX_NAME,
I.NUM_ROWS NUM_ROWS,
SUM(TC.AVG_COL_LEN + 1) + 7 ROWLEN,
I.LEAF_BLOCKS LEAVES,
ROUND((SUM(TC.AVG_COL_LEN + 1) + 7) * I.NUM_ROWS /1000000, 0) NET_MB,
ROUND(I.LEAF_BLOCKS * (8079 - 23 * NVL(I.INI_TRANS, 2)) * (1 - NVL(I.PCT_FREE,
10) / 100) / 1000000, 0) GROSS_MB,
ROUND((SUM(TC.AVG_COL_LEN + 1) + 7) * I.NUM_ROWS / (I.LEAF_BLOCKS * (8079
- 23 * NVL(I.INI_TRANS, 2)) * (1 - NVL(I.PCT_FREE, 10) / 100)) * 100, 0) QUALITY
FROM
DBA_INDEXES I, DBA_IND_COLUMNS IC, DBA_TAB_COLUMNS TC
WHERE I.INDEX_NAME = IC.INDEX_NAME AND
I.OWNER = IC.INDEX_OWNER AND
TC.TABLE_NAME = IC.TABLE_NAME AND
TC.OWNER = IC.INDEX_OWNER AND
TC.COLUMN_NAME = IC.COLUMN_NAME AND
I.INDEX_TYPE = 'NORMAL' AND
I.LEAF_BLOCKS = &gt
GROUP BY I.NUM_ROWS, I.LEAF_BLOCKS, I.INDEX_NAME, I.INI_TRANS, I.PCT_FREE
) ORDER BY QUALITY;

[In our case Values obtained from threshold frequencies


85,110,130,140,145,155,175,185,190,255,275,400,425,445,485,510,605,755,970,1020]

If we choose to rebuilt anyway:

INDEX REBUILT:

The ALTER INDEX index_name REBUILD command is very safe way to rebuild
indexes. Here is the syntax of the command:

alter index index_name


rebuild
tablespace tablespace_name
storage (initial new_initial next new_next freelists new_freelist_number )

Unlike the traditional method where we drop the index and recreate it, the REBUILD command
does not require a full table scan of the table, and the subsequent sorting of the keys and rowids.
Rather, the REBUILD command will perform the following steps:
1. Walk the existing index to get the index keys.
2. Populate temporary segments with the new tree structure.
3. Once the operation has completed successfully, drop the old tree, and rename the
temporary segments to the new index.

As you can see from the steps, you can rebuild indexes without worrying that you will accidentally
lose the index. If the index cannot be rebuilt for any reason, Oracle will abort the operation and
leave the existing index intact. Only after the entire index has been rebuilt does Oracle transfer
the index to the new b-tree.
Note that the TABLESPACE clause should always be used with the ALTER INDEX REBUILD
command to ensure that the index is not rebuilt within the default tablespace (usually SYS).

alter index CUSTOMER_LASTNAME_IND rebuild


parallel nologging compute statistics tablespace IndexData;

The PARALLEL clause causes Oracle to select a degree of parallelism equal to the number of
CPUs available on all participating instances multiplied by the value of the
PARALLEL_THREADS_PER_CPU initialization parameter.

The NOLOGGING clause allows you to rebuild the index faster because operations will not be
logged in the redo log file.

The COMPUTE STATISTICS clause enables you to collect statistics at relatively little cost during
the rebuilding of an index.

The TABLESPACE clause specifies the tablespace where the rebuilt index, index partition, or
index subpartition will be stored. The default is the default tablespace where the index or partition
resided before you rebuilt it. By specifying a different tablespace you can easily move the index to
another location.

Vous aimerez peut-être aussi