1. 程式人生 > >Oracle hint之ORDERED和USE_NL

Oracle hint之ORDERED和USE_NL

lec rst 選擇 sel 使用 ner where plan account

Hint:ORDERED和USE_NL

ORDERED好理解,就是表示根據 from 後面表的順序join,從左到右,左邊的表做驅動表
use_nl(t1,t2):表示對表t1、t2關聯時采用嵌套循環連接,其並不能讓優化器確定誰是驅動表或誰是被驅動的表
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
如果指定的表是outer table(驅動表),則優化器會忽略這個hint
如果非要強制它作為inner table,可以配上ordered參數
oradered 表示根據from 後面表的順序,從左到右join,左表做驅動表,3個或3個以上最有用
也就是說use_nl如果只帶了一個表名作為參數,則該表為被驅動表
如果帶了2個以上的參數,Oracle並沒有指出use_nl(a,b)中哪個是驅動表,所以常使用ordered或者full()或者index()來強化我們的目標

以下是測試:

[sql]
[email protected]> select first_name,departments.department_id from employees,departments where employees.department_id=departments.department_id;

Execution Plan
----------------------------------------------------------
Plan hash value: 169719308

---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 106 | 1484 | 3 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | 106 | 1484 | 3 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL| EMPLOYEES | 107 | 1070 | 3 (0)| 00:00:01 |
|* 3 | INDEX UNIQUE SCAN| DEPT_ID_PK | 1 | 4 | 0 (0)| 00:00:01 |
---------------------------------------------------------------------------------

此處優化器選擇employees作為驅動表,因為departments上有索引,而且索引正好建立在連接列上
[sql]
[email protected]> select /*+ use_nl(employees) */ first_name,departments.department_id from employees,departments where employees.department_id=departments.department_id;

Execution Plan
----------------------------------------------------------
Plan hash value: 169719308

---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 106 | 1484 | 3 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | 106 | 1484 | 3 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL| EMPLOYEES | 107 | 1070 | 3 (0)| 00:00:01 |
|* 3 | INDEX UNIQUE SCAN| DEPT_ID_PK | 1 | 4 | 0 (0)| 00:00:01 |
---------------------------------------------------------------------------------

由於employees是作為驅動表,優化器會忽略hint提示
[sql]
[email protected]> select /*+ ordered use_nl(employees) */ first_name,departments.department_id from departments,employees where employees.department_id=departments.department_id;

Execution Plan
----------------------------------------------------------
Plan hash value: 2677871237

-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 106 | 1484 | 8 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES | 4 | 40 | 1 (0)| 00:00:01 |
| 2 | NESTED LOOPS | | 106 | 1484 | 8 (0)| 00:00:01 |
| 3 | INDEX FULL SCAN | DEPT_ID_PK | 27 | 108 | 1 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | EMP_DEPARTMENT_IX | 10 | | 0 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------

現在是departments作為驅動表了.

Oracle hint之ORDERED和USE_NL