What is index clustering factor?
In the world of Oracle performance tuning, you might find two indexes that look identical on paper, but one is lightning-fast and the other is painfully slow. Often, the hidden culprit is the Clustering Factor.
If an index is the "map" to your data, the Clustering Factor tells you how "organized" the actual data is on the shelf.
The Clustering Factor is a measurement of how well the order of an index matches the physical order of the rows in the table.
Oracle calculates this by scanning the index from start to finish and checking the ROWID (the physical address) of each entry.
Every time the ROWID points to a different data block than the previous entry, the counter goes up.
If the next entry points to the same block, the counter stays the same.
The Clustering Factor will always fall somewhere between the number of Blocks in the table and the number of Rows in the table.
This means the data is physically sorted in the same order as the index.
The Result: Oracle can grab a leaf of the index, go to one block on the disk, and find all the rows it needs.
Performance: Extremely efficient; low I/O.
This means the data is scattered randomly across the disk.
The Result: For every single entry in the index, Oracle has to jump to a completely different data block. If you are fetching 1,000 rows, Oracle might have to perform 1,000 separate physical reads.
Performance: Very slow; high I/O wait times.
Imagine a library where the Index is a list of "Books by Author."
Good Clustering Factor: You look up "Hemingway" and find all his books sitting together on Shelf 12. You walk to the shelf once and grab them all.
Bad Clustering Factor: You look up "Hemingway" and find one book on Shelf 1, one in the basement, and one in the attic. You are exhausted from walking (that’s the "Disk I/O").
The Cost-Based Optimizer (CBO) uses the Clustering Factor to decide whether or not to use an index.
If the Clustering Factor is low, the CBO sees the index as "cheap" and will use it.
If the Clustering Factor is high, the CBO might decide that using the index is more expensive than just scanning the entire table (Full Table Scan), even if an index exists!
Random Inserts: If you have an index on LAST_NAME, but you insert rows into the table based on a random TIMESTAMP, the names will be scattered everywhere.
Heavy Deletes/Updates: Over time, as rows are deleted and new ones are inserted into empty spots, the physical order of the table becomes "fragmented" compared to the index.
You can see the clustering factor for your indexes by querying the data dictionary:
SELECT index_name, leaf_blocks, clustering_factor, num_rows
FROM user_indexes
WHERE table_name = 'YOUR_TABLE_NAME';
Compare: If CLUSTERING_FACTOR is close to NUM_ROWS, your index is poorly clustered.
The only way to "fix" a clustering factor is to physically reorder the table. You can do this by using ALTER TABLE ... MOVE and sorting the data by the index column, or by recreating the table using a CTAS (Create Table As Select) with an ORDER BY clause.
Note: You can usually only optimize a table for one index. If you sort the table for LAST_NAME, you might ruin the clustering factor for ZIP_CODE!