* Full outer join is basically a union all between an outer join and a anti join. I.e. a union all of (test1 left outer join test2) and (all the rows in test2 not in test1) <- the anti join * Hint seems only be able to reach the outer join part of the full outer join. Anti join part can not be hinted. * However, full outer join can be decomposed into a union all of of the above mentioned 2 selects. 2 hints can then be applied to them separatedly. Since the execution plan are identical, performance should be alike. Though the union all query would take a little longer to parse, maybe negligible. * This is also how full outer join was handled before ORACLE started supporting ANSI full outer join syntax - with union all of outer join and anti join. * Note that ORACLE will not obey the *_aj hints unless the columns involved are defined as NOT NULL. SQL> select * from test1 full outer join test2 on test1.c1=test2.c1; Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=7 Card=24 Bytes=1080 ) 1 0 VIEW (Cost=7 Card=24 Bytes=1080) 2 1 UNION-ALL 3 2 HASH JOIN (OUTER) (Cost=5 Card=23 Bytes=230) 4 3 TABLE ACCESS (FULL) OF 'TEST1' (Cost=2 Card=23 Bytes =138) 5 3 TABLE ACCESS (FULL) OF 'TEST2' (Cost=2 Card=9 Bytes= 36) 6 2 NESTED LOOPS (ANTI) (Cost=2 Card=1 Bytes=5) 7 6 TABLE ACCESS (FULL) OF 'TEST2' (Cost=2 Card=9 Bytes= 36) 8 6 INDEX (RANGE SCAN) OF 'TEST_C1_IDX' (NON-UNIQUE) SQL> select --+ use_merge(test2) 2 * from test1 full outer join test2 on test1.c1=test2.c1; Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=9 Card=24 Bytes=1080 ) 1 0 VIEW (Cost=9 Card=24 Bytes=1080) 2 1 UNION-ALL 3 2 MERGE JOIN (OUTER) (Cost=7 Card=23 Bytes=230) 4 3 SORT (JOIN) (Cost=4 Card=23 Bytes=138) 5 4 TABLE ACCESS (FULL) OF 'TEST1' (Cost=2 Card=23 Byt es=138) 6 3 SORT (JOIN) (Cost=4 Card=9 Bytes=36) 7 6 TABLE ACCESS (FULL) OF 'TEST2' (Cost=2 Card=9 Byte s=36) 8 2 NESTED LOOPS (ANTI) (Cost=2 Card=1 Bytes=5) 9 8 TABLE ACCESS (FULL) OF 'TEST2' (Cost=2 Card=9 Bytes= 36) 10 8 INDEX (RANGE SCAN) OF 'TEST_C1_IDX' (NON-UNIQUE) SQL> select * from test1 left outer join test2 on test1.c1=test2.c1 2 union all 3 select null,null,null,c1,c2 from test2 where test2.c1 not in (select /*+ merge_aj */ c1 from te st1); Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=12 Card=24 Bytes=235 ) 1 0 UNION-ALL 2 1 HASH JOIN (OUTER) (Cost=5 Card=23 Bytes=230) 3 2 TABLE ACCESS (FULL) OF 'TEST1' (Cost=2 Card=23 Bytes=1 38) 4 2 TABLE ACCESS (FULL) OF 'TEST2' (Cost=2 Card=9 Bytes=36 ) 5 1 MERGE JOIN (ANTI) (Cost=7 Card=1 Bytes=5) 6 5 SORT (JOIN) (Cost=4 Card=9 Bytes=36) 7 6 TABLE ACCESS (FULL) OF 'TEST2' (Cost=2 Card=9 Bytes= 36) 8 5 SORT (UNIQUE) (Cost=4 Card=23 Bytes=23) 9 8 TABLE ACCESS (FULL) OF 'TEST1' (Cost=2 Card=23 Bytes =23) SQL>