Join Methods –
Oracle
Execution plans provide the sequence of operations
performed in order to run SQL statements.
•Order of
the tables referenced in the statement
•Access method for each table in the statement
–INDEX
–INLIST ITERATOR
–TABLE ACCESS
–VIEW
•Join method in statement accessing multiple tables
–HASH JOIN
–MERGE JOIN
–NESTED LOOPS
•Data manipulations
–CONCATENATION
–COUNT
–FILTER
–SORT
7369 SMITH CLERK 7902 17-DEC-80 800 20
7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30
7521 WARD SALESMAN 7698 22-FEB-81 1250 500 30
7566 JONES MANAGER 7839 02-APR-81 2975 20
7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30
7698 BLAKE MANAGER 7839 01-MAY-81 2850 30
7782 CLARK MANAGER 7839 09-JUN-81 2450 10
7788 SCOTT ANALYST 7566 19-APR-87 3000 20
7839 KING PRESIDENT 17-NOV-81 5000 10
7844 TURNER SALESMAN 7698 08-SEP-81 1500 0 30
7876 ADAMS CLERK 7788 23-MAY-87 1100 20
7900 JAMES CLERK 7698 03-DEC-81 950 30
7902 FORD ANALYST 7566 03-DEC-81 3000 20
7934 MILLER CLERK 7782 23-JAN-82 1300 10
14 rows selected.
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
Nested loop Joins
cost = access cost of A + (access cost of B * no_of_rows from A)
2. The other table is designated as the inner table.
3. For every row in the outer table, Oracle accesses all the rows in the inner table.
WHERE dept.deptno = 10
AND emp.deptno = dept.deptno
/
WHERE dept.deptno = 10
AND emp.deptno = dept.deptno
/
EMPNO DNAME
---------- --------------
7782 ACCOUNTING
7839 ACCOUNTING
7934 ACCOUNTING
---------------------------------------------------------------------
Plan hash value: 568005898
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3 | 60 | 3 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | 3 | 60 | 3 (0)| 00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 13 | 1 (0)| 00:00:01 |
|* 3 | INDEX UNIQUE SCAN | PK_DEPT | 1 | | 0 (0)| 00:00:01 |
|* 4 | TABLE ACCESS FULL | EMP | 3 | 21 | 2 (0)| 00:00:01 |
----------------------------------------------------------------------------------------
---------------------------------------------------
4 - filter("EMP"."DEPTNO"=10)
2 SELECT /*+ USE_NL(emp dept) */ emp.empno, dept.dname
FROM EMP , DEPT WHERE dept.deptno = 10
AND emp.deptno = dept.deptno 3 4
5 /
-----------------------------------------------------------------------------
Plan hash value: 568005898
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3 | 60 | 3 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | 3 | 60 | 3 (0)| 00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 13 | 1 (0)| 00:00:01 |
|* 3 | INDEX UNIQUE SCAN | PK_DEPT | 1 | | 0 (0)| 00:00:01 |
|* 4 | TABLE ACCESS FULL | EMP | 3 | 21 | 2 (0)| 00:00:01 |
----------------------------------------------------------------------------------------
---------------------------------------------------
4 - filter("EMP"."DEPTNO"=10)
Table 1. NESTED LOOPS (DEPT
is the driving table)
We can also force the Nested
loop join hint as below.
SELECT /*+ USE_NL(emp dept)
*/ emp.empno, dept.dname
FROM EMP , DEPT WHERE
dept.deptno = 10
AND emp.deptno = dept.deptno
Hash Join
The cost of a Hash loop join is calculated by the following formula:
cost=(access cost of A*no_of_hash partitions of B) + access cost of B
SQL> explain plan for
2 SELECT emp.empno, dept.dname FROM EMP , DEPT
WHERE emp.deptno = dept.deptno; 3
Explained.
SQL> @?/rdbms/admin/utlxpls.sql
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------
Plan hash value: 615168685
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 14 | 280 | 5 (20)| 00:00:01 |
|* 1 | HASH JOIN | | 14 | 280 | 5 (20)| 00:00:01 |
| 2 | TABLE ACCESS FULL| DEPT | 4 | 52 | 2 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| EMP | 14 | 98 | 2 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("EMP"."DEPTNO"="DEPT"."DEPTNO")
15 rows selected.
We can also force the Hash join hint as below.
SELECT /*+USE_HASH(emp dept) */ emp.empno, dept.dname
FROM EMP , DEPT
WHERE emp.deptno = dept.deptno
Sort-Merge
Join
2. A sort operation does not have to be done.
The join consists of two steps:
Sort join operation: Both the inputs are sorted on the join key.
Merge join operation: The sorted lists are merged together.
2. OPTIMIZER_MODE is set to RULE.
3. HASH_JOIN_ENABLED is false.
4. Because of sorts already required by other operations, the optimizer finds it is cheaper to use a sort merge than a hash join.
5. The optimizer thinks that the cost of a hash join is higher, based on the settings of HASH_AREA_SIZE and SORT_AREA_SIZE.
cost = access cost of A + access cost of B + (sort cost of A + sort cost of B)
2 SELECT emp.empno, dept.dname
FROM EMP , DEPT
WHERE emp.deptno < dept.deptno
/
Explained.
SQL>
SQL> @?/rdbms/admin/utlxpls.sql
-----------------------------------------------------------------------------------
Plan hash value: 513559243
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 28 | 560 | 5 (20)| 00:00:01 |
| 1 | MERGE JOIN | | 28 | 560 | 5 (20)| 00:00:01 |
| 2 | SORT JOIN | | 4 | 52 | 2 (0)| 00:00:01 |
| 3 | TABLE ACCESS BY INDEX ROWID| DEPT | 4 | 52 | 2 (0)| 00:00:01 |
| 4 | INDEX FULL SCAN | PK_DEPT | 4 | | 1 (0)| 00:00:01 |
|* 5 | SORT JOIN | | 14 | 98 | 3 (34)| 00:00:01 |
| 6 | TABLE ACCESS FULL | EMP | 14 | 98 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------
---------------------------------------------------
))
filter(INTERNAL_FUNCTION("EMP"."DEPTNO")<INTERNAL_FUNCTION("DEPT"."DEPTNO"
))
A Cartesian join is used when one or more of the tables does not have any join conditions to any other tables in the statement. The optimizer joins every row from one data source with all the row from the other data source, creating the Cartesian product of the two sets.
scott@DB1.US.ORACLE.COM> select * from emp,dept;
2 select * from emp,dept;
-------------------------------------------------------------------------------------------------
Plan hash value: 2034389985
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 56 | 3248 | 5 (0)| 00:00:01 |
| 1 | MERGE JOIN CARTESIAN| | 56 | 3248 | 5 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL | DEPT | 4 | 80 | 2 (0)| 00:00:01 |
| 3 | BUFFER SORT | | 14 | 532 | 3 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL | EMP | 14 | 532 | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------
SQL>
No comments:
Post a Comment