select /*+ORDERED USE_NL(EMP)*/ empno,DNAME from emp, dept
where emp.deptno = dept.deptno;
为什么执行计划走到不是NL而是HASH JOIN
Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=5 Card=82 Bytes=3936)
   1    0   HASH JOIN (Cost=5 Card=82 Bytes=3936)
   2    1     TABLE ACCESS (FULL) OF 'EMP' (Cost=2 Card=82 Bytes=2132)
   3    1     TABLE ACCESS (FULL) OF 'DEPT' (Cost=2 Card=82 Bytes=1804)而且,网上很多例子和我运行效果不一样,是什么原因?例如下面的
网络上的HASH连接的例子:
SQL> explain plan for   
select /*+ use_hash(emp) */ empno   
from emp, dept   
where emp.deptno = dept.deptno;   
Query Plan   
SELECT STATEMENT [CHOOSE] Cost=33 A)
HASH JOIN   
TABLE ACCESS FULL DEPT   
TABLE ACCESS FULL EMP我运行的结果:Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=82 Bytes=3198)
   1    0   NESTED LOOPS (Cost=2 Card=82 Bytes=3198)
   2    1     TABLE ACCESS (FULL) OF 'EMP' (Cost=2 Card=82 Bytes=2132)
   3    1     INDEX (UNIQUE SCAN) OF 'PK_DEPT' (UNIQUE)注明:我的环境是Connected to Oracle9i Enterprise Edition Release 9.2.0.1.0 
努力学习语句优化中,给点指点....

解决方案 »

  1.   

    下面个执行计划我知道了,应该把两个表都写进HASH参数
    select /*+ use_hash(emp,dept) */ empno   
    from emp, dept   
    where emp.deptno = dept.deptno;  
    得到的执行计划就是HASH JOIN了
    Execution Plan
    ----------------------------------------------------------
       0      SELECT STATEMENT Optimizer=CHOOSE (Cost=5 Card=82 Bytes=3198 )
       1    0   HASH JOIN (Cost=5 Card=82 Bytes=3198)
       2    1     TABLE ACCESS (FULL) OF 'EMP' (Cost=2 Card=82 Bytes=2132)
       3    1     TABLE ACCESS (FULL) OF 'DEPT' (Cost=2 Card=82 Bytes=1066 ) 
      

  2.   

    与hash join一样,试试这个
    select /*+ORDERED USE_NL(EMP,DEPT)*/ empno,DNAME from emp, dept
    where emp.deptno = dept.deptno;
      

  3.   

    USE_NL  The USE_NL hint causes Oracle to join each specified table to another row source with a nested loops join using the specified table as the inner table. The syntax of the USE_NL hint is USE_NL(table table) where table is the name or alias of a table to be used as the inner table of a nested loops join.  USE_HASH  The USE_HASH hint causes Oracle to join each specified table with another row source with a hash join. The syntax of the USE_HASH hint is USE_HASH(table table) where table is a table to be joined to the row source resulting from joining the previous tables in the join order using a hash join.  
      

  4.   

    select /*+ORDERED USE_NL(EMP,DEPT)*/ empno,DNAME from emp, dept
    where emp.deptno = dept.deptno;
    这个的我知道的,可是,应该只是EMP作为内部表啊,而DEPT的外部表才对,都把它放到里面,
    之前也认真查过此种方法,转自如下
    USE_NL(),先看看oracle doc怎么说:
    In this statement, the USE_NL hint explicitly chooses a nested loops join with the customers table as the inner table:
    SELECT /*+ ORDERED USE_NL(customers) to get first row faster */
    accounts.balance, customers.last_name, customers.first_name
    FROM accounts, customers
    WHERE accounts.customer_id = customers.customer_id;
    customers 作为inner table,也就是说作为被驱动表。驱动表称为outer table。
    也就是说use_nl如果只带了一个表名作为参数,则该表为被驱动表。
    如果带了2个以上的参数,oracle 并没有指出 use_nl(a b) 中 哪个是驱动表,所以常使用 ordered 或者 full() 或者 index() 来强化我们的目标
    而使用
    select /*+ORDERED USE_NL(dept)*/ empno,DNAME from emp, dept
    where emp.deptno = dept.deptno;时执行计划显示正常,
    所以用EMP作为驱动表时候执行计划用HJ才奇怪,我已经强制使用了NL提示了啊,应该无条件按照NL方式执行才对啊,......疑问
      

  5.   

    找到答案了,http://grassbell.itpub.net/post/26/12950select /*+ORDERED USE_NL(EMP)*/ empno,DNAME from emp, dept
    where emp.deptno = dept.deptno;
    EMP的DEPTNO是索引,仍然走hash join,虽然很想知道为什么,但是记住就可以了,这的优化规则而已..