DBA_INDEXES and DBA_SEGMENTS mismatch
This is a fun one.
We developed a script to process certain indexes on a database somehow, it kept missing some of the indexes that clearly existed. We then found the problem: DBA_INDEXES had more entries than DBA_SEGMENTS. See the following example:
SQL> SELECT owner, index_name as i_name from dba_indexes WHERE owner = 'SIMON'
2 MINUS
3 SELECT owner, segment_name as i_name FROM dba_segments WHERE owner = 'SIMON';
OWNER I_NAME
-------------------- --------------------------------------------------
SIMON IDX_...
SIMON IDX_...
SIMON IDX_...
SIMON PK_...
SIMON PK_...
SIMON UNQ_...
SIMON UNQ_...
7 rows selected.
So here we see that there are clearly indexes for which there are no segments. We then looked at the tables where these indexes are located and noticed a particular thing: All the corresponding tables for these indexes were empty.
So the reason for this behaviour is called “Deferred Segment Creation“. This means that when a “CREATE TABLE” statement is issued and no rows are inserted, there are no segments that are created. This behaviour can be controlled by the DEFERRED_SEGMENT_CREATION parameter.
This makes sense in large schemas, where not all tables are populated. Instead of having segments created and extents allocated, only the definition of the table is saved. As soon as the table has at least one row, the segments are automatically created.