SQLクエリにおいて、結合順序に関連するHintにはORDEREDHintとLEADINGHintが含まれます。
| ヒントタイプ | 説明 |
|---|---|
LEADING |
ヒントで指定されたテーブルの順序で結合を実行します。FROM 句で一部のテーブルのみが指定されている場合、指定されたテーブルがドライバーとして他のテーブルと結合されます。 |
ORDERED |
FROM 句の順序でテーブルを結合します。 |
注意
LEADINGHintを使用して、希望する結合順序を明示的に指定することを推奨します。ORDEREDHintは特定の結合順序のみを指定でき、かつ結合順序は書き換えの影響を受けるためです。
LEADING ヒント
LEADING ヒントは、オプティマイザーに対し、指定された順序でテーブルを結合するよう指示します。これは ORDERED ヒントよりも柔軟性が高く、任意の有効な期待される結合順序を明示的に定義できます。一方、ORDERED ヒントは特定の結合順序のみを指定でき、しかもその結合順序は書き換えによって影響を受けます。期待される結合順序を直接明示的に指定するためには、LEADING ヒントの使用を推奨します。
構文
/*+ LEADING ( [ @queryblock ] tablespec [ tablespec ]... ) */
使用方法と注意点
LEADING ヒントは、指定されたテーブル名がクエリ内のテーブル名と完全に一致する場合にのみ有効になります。
ヒントで指定された
table_nameが存在しないことが判明した場合、LEADINGヒントは無効になります。ヒント内に重複するテーブルが存在する場合、
LEADINGヒントは無効になります。オプティマイザーの結合処理中に対応するテーブルを見つけられない場合、そのテーブル以降のテーブルに指定された結合順序は無効になり、そのテーブルより前に指定された順序は引き続き有効です。
結合グラフ内の依存関係により、指定された順序で最初に指定されたテーブルを結合できない場合、
LEADINGヒントは無効になります。互いに矛盾する 2 つ以上の
LEADINGヒントを指定した場合、LEADINGヒントは無効になります。ORDEREDヒントを指定した場合、すべてのLEADINGヒントが上書きされます。
例
SELECT /*+ LEADING(e j) */ *
FROM employees e, departments d, job_history j
WHERE e.department_id = d.department_id
AND e.hire_date = j.start_date;
-- 実行計画を確認する
EXPLAIN SELECT /*+ LEADING(e j) */ *
FROM employees e, departments d, job_history j
WHERE e.department_id = d.department_id
AND e.hire_date = j.start_date;
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Query Plan |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| =================================================== |
| |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| |
| --------------------------------------------------- |
| |0 |HASH JOIN | |3 |16 | |
| |1 |├─HASH JOIN | |3 |10 | |
| |2 |│ ├─TABLE FULL SCAN|E |3 |5 | |
| |3 |│ └─TABLE FULL SCAN|J |3 |4 | |
| |4 |└─TABLE FULL SCAN |D |3 |4 | |
| =================================================== |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([E.EMPLOYEE_ID], [E.FIRST_NAME], [E.LAST_NAME], [E.HIRE_DATE], [E.DEPARTMENT_ID], [D.DEPARTMENT_ID], [D.DEPARTMENT_NAME], [J.EMPLOYEE_ID], |
| [J.START_DATE], [J.END_DATE], [J.JOB_ID]), filter(nil), rowset=16 |
| equal_conds([E.DEPARTMENT_ID = D.DEPARTMENT_ID]), other_conds(nil) |
| 1 - output([E.EMPLOYEE_ID], [E.FIRST_NAME], [E.LAST_NAME], [E.HIRE_DATE], [E.DEPARTMENT_ID], [J.EMPLOYEE_ID], [J.START_DATE], [J.END_DATE], [J.JOB_ID]), filter(nil), rowset=16 |
| equal_conds([E.HIRE_DATE = J.START_DATE]), other_conds(nil) |
| 2 - output([E.EMPLOYEE_ID], [E.DEPARTMENT_ID], [E.HIRE_DATE], [E.FIRST_NAME], [E.LAST_NAME]), filter(nil), rowset=16 |
| access([E.EMPLOYEE_ID], [E.DEPARTMENT_ID], [E.HIRE_DATE], [E.FIRST_NAME], [E.LAST_NAME]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([E.EMPLOYEE_ID]), range(MIN ; MAX)always true |
| 3 - output([J.START_DATE], [J.EMPLOYEE_ID], [J.END_DATE], [J.JOB_ID]), filter(nil), rowset=16 |
| access([J.START_DATE], [J.EMPLOYEE_ID], [J.END_DATE], [J.JOB_ID]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([J.__pk_increment]), range(MIN ; MAX)always true |
| 4 - output([D.DEPARTMENT_ID], [D.DEPARTMENT_NAME]), filter(nil), rowset=16 |
| access([D.DEPARTMENT_ID], [D.DEPARTMENT_NAME]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([D.DEPARTMENT_ID]), range(MIN ; MAX)always true |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
28 rows in set
上記の実行計画において、LEADING(e j) はオプティマイザーがまずテーブル e (employees) を考慮し、次にテーブル j (job_history) を考慮することを示します。
ORDERED ヒント
クエリでデフォルトの結合順序を使用します。ORDERED ヒントは LEADING ヒントよりも優先順位が高く、ORDERED ヒントが存在する場合、LEADING ヒントは無効になります。 ORDERED ヒントを使用すると、OUTLINE DATAには ORDERED ヒントが表示されず、代わりに完全な LEADING ヒントが出力されます。
構文
/*+ ORDERED */
例
3つのテーブル employees、departments、および job_history を結合する必要があるとします。
SELECT /*+ ORDERED */ e.employee_id, d.department_name, j.job_id
FROM employees e, departments d, job_history j
WHERE e.department_id = d.department_id
AND e.hire_date = j.start_date;
この例では、データベースは employees、departments、および job_history の順序でこれら3つのテーブルを結合します。