Originally posted by DreamWarrior
The reason is that simply any of those statements disallow index usage.
Where do you get that from?
Code:
After creating a PK on dept(deptno)

select * from emp 
where deptno not in (select deptno from dept)
/

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=1 Bytes=32)
   1    0   FILTER
   2    1     TABLE ACCESS (FULL) OF 'EMP' (Cost=1 Card=1 Bytes=32)
   3    1     INDEX (FULL SCAN) OF 'DEPT_PK' (UNIQUE) (Cost=1 Card=1 Bytes=2)


select * from emp e
where not exists
(select * from dept d
 where  d.deptno=e.deptno)
/

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=1 Bytes=32)
   1    0   FILTER
   2    1     TABLE ACCESS (FULL) OF 'EMP' (Cost=1 Card=1 Bytes=32)
   3    1     INDEX (UNIQUE SCAN) OF 'DEPT_PK' (UNIQUE)
I would agree that NOT logic makes it less likely that an index will be used, simply because it is typically less selective and if, say, 95% of a table will be selected, a FTS is preferable. Trivial example:
SELECT * FROM my_table WHERE primaryKex <> 123;
will select the whole table less (possibly) one row and hence use FTS.
(No prizes given for constructing counter examples where <> is more selective than =).

I would add once again my preference for (NOT) EXISTS over (NOT) IN
- NOT IN handles NULL's in an unexpected way.
- in my experience (NOT) EXISTS performs as well or better than (NOT) IN and almost never worse (check the different index use in the explain plans above) - though the Oracle Tuning Manual gives two examples where IN is claimed to be better than EXISTS.