Well, lets be clear here. Its always ONLY been true that the order of the tables in the from clause MAY affect the query plan in the RBO. Stress the keywords ONLY and MAY. It is true that in RBO, the order of tables in the from clause can be important. It is true that in CBO, it is not so. It is true that in RBO, it will use RULES to process the query and these rules govern how the tables will be accessed.
Here is the simplest example that shows the same query using different driving tables under RBO. I just play games with the indexes -- the RBO uses its rules to find the driving table using the indexes, not the order of the tables in the from clause.
ops$tkyte@ORA817DEV.US.ORACLE.COM> create table emp as select * from scott.emp;
Table created.
ops$tkyte@ORA817DEV.US.ORACLE.COM> create table dept as select * from scott.dept;
Table created.
ops$tkyte@ORA817DEV.US.ORACLE.COM> set autotrace traceonly explain
ops$tkyte@ORA817DEV.US.ORACLE.COM> create index dept_idx on dept(deptno);
Index created.
ops$tkyte@ORA817DEV.US.ORACLE.COM> select * from emp, dept where emp.deptno = dept.deptno;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 NESTED LOOPS
2 1 TABLE ACCESS (FULL) OF 'EMP'
3 1 TABLE ACCESS (BY INDEX ROWID) OF 'DEPT'
4 3 INDEX (RANGE SCAN) OF 'DEPT_IDX' (NON-UNIQUE)
<b>so here, EMP is the "driving" table, we full scan it and do an index access into DEPT</b>
ops$tkyte@ORA817DEV.US.ORACLE.COM> drop index dept_idx;
Index dropped.
ops$tkyte@ORA817DEV.US.ORACLE.COM> create index emp_idx on emp(deptno);
Index created.
ops$tkyte@ORA817DEV.US.ORACLE.COM> select * from emp, dept where emp.deptno = dept.deptno;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 NESTED LOOPS
2 1 TABLE ACCESS (FULL) OF 'DEPT'
3 1 TABLE ACCESS (BY INDEX ROWID) OF 'EMP'
4 3 INDEX (RANGE SCAN) OF 'EMP_IDX' (NON-UNIQUE)
<b>same query, different indexes -- the roles are reversed. DEPT drives, EMP is driven into</b>
ops$tkyte@ORA817DEV.US.ORACLE.COM> create index dept_idx on dept(deptno);
Index created.
<b>Now they both have equally "appealing" indexes -- the order of the tables in the from clause is used to break the tie</b>
ops$tkyte@ORA817DEV.US.ORACLE.COM> select * from emp, dept where emp.deptno = dept.deptno;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 NESTED LOOPS
2 1 TABLE ACCESS (FULL) OF 'DEPT'
3 1 TABLE ACCESS (BY INDEX ROWID) OF 'EMP'
4 3 INDEX (RANGE SCAN) OF 'EMP_IDX' (NON-UNIQUE)
ops$tkyte@ORA817DEV.US.ORACLE.COM> select * from dept, emp where emp.deptno = dept.deptno;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 NESTED LOOPS
2 1 TABLE ACCESS (FULL) OF 'EMP'
3 1 TABLE ACCESS (BY INDEX ROWID) OF 'DEPT'
4 3 INDEX (RANGE SCAN) OF 'DEPT_IDX' (NON-UNIQUE)
ops$tkyte@ORA817DEV.US.ORACLE.COM>
ops$tkyte@ORA817DEV.US.ORACLE.COM> set autotrace off