Your test is badly formed because ...
  • the optimizer doesn't know that the "id" column is not null.
  • placing the object_type second in the list of columns in the composite index reduces the chances of it being used
  • The table is so small that the optimizer might choose to use an FTS anyway
  • Since all the values of object_type are null, it's more efficient with this data set to FTS anyway



Code:
SQL> create table my_table as select * from dba_objects;

Table created.

SQL> update my_table set object_type = null
  2  where rownum < 11;

10 rows updated.

SQL> desc my_table
 Name                                      Null?    Type
 ----------------------------------------- -------- --------------------------

 OWNER                                              VARCHAR2(30)
 OBJECT_NAME                                        VARCHAR2(128)
 SUBOBJECT_NAME                                     VARCHAR2(30)
 OBJECT_ID                                          NUMBER
 DATA_OBJECT_ID                                     NUMBER
 OBJECT_TYPE                                        VARCHAR2(18)
 CREATED                                            DATE
 LAST_DDL_TIME                                      DATE
 TIMESTAMP                                          VARCHAR2(19)
 STATUS                                             VARCHAR2(7)
 TEMPORARY                                          VARCHAR2(1)
 GENERATED                                          VARCHAR2(1)
 SECONDARY                                          VARCHAR2(1)

SQL> alter table my_table modify (owner not null);

Table altered.

SQL> create index my_index on my_table (object_type,owner);

Index created.

SQL> analyze table my_table compute statistics;

Table analyzed.

SQL> set autotrace traceonly explain
SQL> select * from my_table where object_type is null;

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=3 Card=10 Bytes=860)
   1    0   TABLE ACCESS (BY INDEX ROWID) OF 'MY_TABLE' (Cost=3 Card=1
          0 Bytes=860)

   2    1     INDEX (RANGE SCAN) OF 'MY_INDEX' (NON-UNIQUE) (Cost=2 Ca
          rd=10)