通过ordered或者leading可以控制连接顺序如下

    1. select
    2. /*+
    3. ordered
    4. use_nl(t2)
    5. use_nl(t3)
    6. use_nl(t4)
    7. */
    8. * from t1,t2,t3,t4
    9. where t1.object_id=t2.object_id
    10. and t2.object_name=t3.object_name
    11. and t3.owner=t4.owner
    12. and t4.owner='MYDB'

    执行计划

    1. \----------------------------------------------------------
    2. Plan hash value: 4050478457
    3. \-----------------------------------------------------------------------------
    4. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    5. \-----------------------------------------------------------------------------
    6. | 0 | SELECT STATEMENT | | 2137 | 801K| 305K (2)| 01:01:03 |
    7. | 1 | NESTED LOOPS | | 2137 | 801K| 305K (2)| 01:01:03 |
    8. | 2 | NESTED LOOPS | | 52 | 14976 | 304K (2)| 01:00:55 |
    9. | 3 | NESTED LOOPS | | 11651 | 2184K| 152K (2)| 00:30:26 |
    10. | 4 | TABLE ACCESS FULL| T1 | 11651 | 1092K| 15 (0)| 00:00:01 |
    11. |* 5 | TABLE ACCESS FULL| T2 | 1 | 96 | 13 (0)| 00:00:01 |
    12. |* 6 | TABLE ACCESS FULL | T3 | 1 | 96 | 13 (0)| 00:00:01 |
    13. |* 7 | TABLE ACCESS FULL | T4 | 41 | 3936 | 13 (0)| 00:00:01 |
    14. \-----------------------------------------------------------------------------
    15. Predicate Information (identified by operation id):
    16. \---------------------------------------------------
    17. 5 - filter("T1"."OBJECT_ID"="T2"."OBJECT_ID")
    18. 6 - filter("T3"."OWNER"='MYDB' AND
    19. "T2"."OBJECT_NAME"="T3"."OBJECT_NAME")
    20. 7 - filter("T4"."OWNER"='MYDB')
    21. Note
    22. \-----
    23. \- dynamic sampling used for this statement

    但是我如何控制由谁来做驱动表呢?

    比如我想实现t1作为驱动表和t2做NL,然后T3作为驱动表和t1,t2的结果集作NL,然后前面的结果集作为驱动表和T4做NL,如下:

    1. NESTED LOOPS
    2. NESTED LOOPS
    3. T3
    4. NESTED LOOPS
    5. T1
    6. T2
    7. T4

    解决方案: 这个leading可以做到。参考下列执行计划

    1. select /*+use_nl(t1 t2 t3)*/
    2. count(*) from
    3. ttt1 t1,
    4. ttt2 t2,
    5. ttt3 t3
    6. where t1.table_name=t2.table_name
    7. and t2.table_name=t3.table_name;
    1. COUNT(*)
    2. ----------
    3. 20
    4. Execution Plan
    5. ----------------------------------------------------------
    6. Plan hash value: 66364841
    7. -----------------------------------------------------------------------------
    8. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    9. -----------------------------------------------------------------------------
    10. | 0 | SELECT STATEMENT | | 1 | 51 | 51 (0)| 00:00:01 |
    11. | 1 | SORT AGGREGATE | | 1 | 51 | | |
    12. | 2 | NESTED LOOPS | | 20 | 1020 | 51 (0)| 00:00:01 |
    13. | 3 | NESTED LOOPS | | 20 | 680 | 27 (0)| 00:00:01 |
    14. | 4 | TABLE ACCESS FULL| TTT1 | 20 | 340 | 3 (0)| 00:00:01 |
    15. |* 5 | TABLE ACCESS FULL| TTT2 | 1 | 17 | 1 (0)| 00:00:01 |
    16. |* 6 | TABLE ACCESS FULL | TTT3 | 1 | 17 | 1 (0)| 00:00:01 |
    17. -----------------------------------------------------------------------------
    18. Predicate Information (identified by operation id):
    19. ---------------------------------------------------
    20. 5 - filter("T1"."TABLE_NAME"="T2"."TABLE_NAME")
    21. 6 - filter("T2"."TABLE_NAME"="T3"."TABLE_NAME")
    1. select /*+use_nl(t1 t2 t3) leading(t2 t3 t1)*/
    2. count(*) from
    3. ttt1 t1,
    4. ttt2 t2,
    5. ttt3 t3
    6. where t1.table_name=t2.table_name
    7. and t2.table_name=t3.table_name;
    1. COUNT(*)
    2. ----------
    3. 20
    4. Execution Plan
    5. ----------------------------------------------------------
    6. Plan hash value: 4222413350
    7. -----------------------------------------------------------------------------
    8. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    9. -----------------------------------------------------------------------------
    10. | 0 | SELECT STATEMENT | | 1 | 51 | 51 (0)| 00:00:01 |
    11. | 1 | SORT AGGREGATE | | 1 | 51 | | |
    12. | 2 | NESTED LOOPS | | 20 | 1020 | 51 (0)| 00:00:01 |
    13. | 3 | NESTED LOOPS | | 20 | 680 | 27 (0)| 00:00:01 |
    14. | 4 | TABLE ACCESS FULL| TTT2 | 20 | 340 | 3 (0)| 00:00:01 |
    15. |* 5 | TABLE ACCESS FULL| TTT3 | 1 | 17 | 1 (0)| 00:00:01 |
    16. |* 6 | TABLE ACCESS FULL | TTT1 | 1 | 17 | 1 (0)| 00:00:01 |
    17. -----------------------------------------------------------------------------
    18. Predicate Information (identified by operation id):
    19. ---------------------------------------------------
    20. 5 - filter("T2"."TABLE_NAME"="T3"."TABLE_NAME")
    21. 6 - filter("T1"."TABLE_NAME"="T2"."TABLE_NAME")
    1. select /*+use_nl(t1 t2 t3) leading(t3 t2 t1)*/
    2. count(*) from
    3. ttt1 t1,
    4. ttt2 t2,
    5. ttt3 t3
    6. where t1.table_name=t2.table_name
    7. and t2.table_name=t3.table_name;
    1. COUNT(*)
    2. ----------
    3. 20
    4. Execution Plan
    5. ----------------------------------------------------------
    6. Plan hash value: 1893606081
    7. -----------------------------------------------------------------------------
    8. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    9. -----------------------------------------------------------------------------
    10. | 0 | SELECT STATEMENT | | 1 | 51 | 51 (0)| 00:00:01 |
    11. | 1 | SORT AGGREGATE | | 1 | 51 | | |
    12. | 2 | NESTED LOOPS | | 20 | 1020 | 51 (0)| 00:00:01 |
    13. | 3 | NESTED LOOPS | | 20 | 680 | 27 (0)| 00:00:01 |
    14. | 4 | TABLE ACCESS FULL| TTT3 | 20 | 340 | 3 (0)| 00:00:01 |
    15. |* 5 | TABLE ACCESS FULL| TTT2 | 1 | 17 | 1 (0)| 00:00:01 |
    16. |* 6 | TABLE ACCESS FULL | TTT1 | 1 | 17 | 1 (0)| 00:00:01 |
    17. -----------------------------------------------------------------------------
    18. Predicate Information (identified by operation id):
    19. ---------------------------------------------------
    20. 5 - filter("T2"."TABLE_NAME"="T3"."TABLE_NAME")
    21. 6 - filter("T1"."TABLE_NAME"="T2"."TABLE_NAME")