Oracle Join Techniques Carl Dudley University of Wolverhampton, UK Oracle ACE Director carl.dudley@wlv.ac.uk Carl Dudley – University of Wolverhampton 1 Introduction Working with Oracle since 1986 Oracle DBA ANSI - OCP Oracle7, 8, 9, 10 and Oracle Joins Oracle DBA of the Year – Joins 2002 Two-way Outer Oracle ACE Director Join and Filter Conditions Beta tester –Chaining Oracle8, 10, 11, Join 12 on9,the Outer Regular Presenter at Oracle Hash Join Trees Conferences Consultant and Anti Trainer Joins and Semi Joins Technical Editor for a number of Oracle texts Lateral Joins UK Oracle User Group Official Nested Loops Joins Member of IOUC Join Elimination Day job – University of Wolverhampton, UK Carl Dudley – University of Wolverhampton 2 The emp and dept Tables dept emp DEPTNO -----10 20 30 40 EMPNO ----7934 7782 7839 7369 7876 7566 7902 7788 7900 7521 7654 7844 7499 7698 DNAME -------------ACCOUNTING RESEARCH SALES OPERATIONS ENAME ---------MILLER CLARK KING SMITH ADAMS JONES FORD SCOTT JAMES WARD MARTIN TURNER ALLEN BLAKE LOC -------NEW YORK DALLAS CHICAGO BOSTON JOB MGR HIREDATE SAL COMM DEPTNO --------- ----- ----------- ----- ----- -----CLERK 7782 23-JAN-1982 1300 10 MANAGER 7839 09-JUN-1981 2450 10 PRESIDENT 17-NOV-1981 5000 10 CLERK 7902 17-DEC-1980 800 20 CLERK 7788 12-JAN-1983 1100 20 MANAGER 7839 02-APR-1981 2975 20 ANALYST 7566 03-DEC-1981 3000 20 ANALYST 7566 09-DEC-1982 3000 20 CLERK 7698 03-DEC-1981 950 30 SALESMAN 7698 22-FEB-1981 1250 500 30 SALESMAN 7698 28-SEP-1981 1250 1400 30 SALESMAN 7698 08-SEP-1981 1500 0 30 SALESMAN 7698 20-FEB-1981 1600 300 30 MANAGER 7839 01-MAY-1981 2850 30 Carl Dudley – University of Wolverhampton 3 ANSI Joins ANSI defined join syntax in ANSI SQL2 Standard (1992) — Oracle finally fully implemented this syntax in Oracle9i Types of joins specified by additional keywords INNER JOIN OUTER JOIN (LEFT RIGHT FULL) CROSS JOIN UNION JOIN (not supported by Oracle) Carl Dudley – University of Wolverhampton 4 Inner UnionJoins Join – ANSI and Oracle Syntax Not in common use– and Oracle Equivalent ANSI based joinshas no support but can be simulated —SELECT Numberename,dname,dept.deptno of columns in each select clause must match —FROM Use NULLs to paddept out the number of columns emp JOIN ON dept.deptno = empa.deptno; SELECT o.*, NULL,...,NULL FROM orders o SELECTUNION ename,dname,deptno FROM emp NATURAL JOIN dept; l.* FROM line_items l SELECT NULL,...,NULL, SELECT ename,dname,deptno FROM emp NATURAL JOIN dept Expected output USING OCOL1 (deptno); OCOL2 LCOL1 LCOL2 ------------— Note the absence of the table ----qualifier for deptno in some of the examples 11111 AAAAA 22222 BBBBB Equivalent Oracle join 33333 CCCCC SELECT ename,dname,dept.deptno 88888 XXXXX FROM emp,dept 99999 YYYYY WHERE emp.deptno = dept.deptno; Carl Dudley – University of Wolverhampton 5 The Join Condition Join condition (ON clause) must be included ― Helps safeguard against inadvertant cartesian products SELECT ename,dname,dept.deptno FROM emp JOIN dept; ORA-00905: missing keyword But join condition does not have to make any sense — Could cause cartesian products SELECT ename,dname,dept.deptno FROM emp JOIN dept ON emp.empno = emp.empno; — Oracle join syntax has no protection Carl Dudley – University of Wolverhampton 6 Multi-table Joins If several tables are to be joined — Use a step-wise process by first joining two of the tables — Then add a further JOIN keyword to join to the third table — Repeat this for each subsequent table — Each join may have its own condition(s) — The joins may be of different types SELECT emp.empno ,emp.ename ,dept.loc ,proj.pname FROM emp JOIN dept ON emp.deptno = dept.deptno JOIN proj ON emp.proj_id = proj.proj_id; Carl Dudley – University of Wolverhampton 7 LEFT and RIGHT Outer Joins The driving table is specified with LEFT or RIGHT — This table will have all its rows included — Dummy NULL rows may be included from the other table Refers to placement of the table name WITHIN the FROM ... JOIN clause The following join clauses are all equivalent FROM emp,dept WHERE emp.deptno(+) = dept.deptno FROM dept LEFT OUTER JOIN emp ON emp.deptno = dept.deptno FROM emp RIGHT OUTER JOIN dept ON emp.deptno = dept.deptno Carl Dudley – University of Wolverhampton 8 Modified Employee Data empa EMPNO ----7782 7788 7844 7499 7902 1111 ENAME -----CLARK SCOTT TURNER ALLEN FORD EXTRA JOB MGR HIREDATE SAL COMM DEPTNO -------- ----- ----------- ---- ----- ------MANAGER 7839 09-JUN-1981 2450 10 ANALYST 7566 19-APR-1987 3000 20 SALESMAN 7698 08-SEP-1981 1500 0 30 SAlESMAN 7698 20-FEB-1981 1600 300 30 ANALYST 7566 03-DEC-1981 3000 20 CEO 01-JAN-1999 500 dept DEPTNO ------10 20 30 40 DNAME ---------ACCOUNTING RESEARCH SALES OPERATIONS LOC -------NEW YORK DALLAS CHICAGO BOSTON Carl Dudley – University of Wolverhampton 9 RIGHT Outer Joins SELECT ename,dname,dept.deptno FROM empa RIGHT OUTER JOIN dept ON empa.deptno = dept.deptno; ENAME ------CLARK SCOTT TURNER FORD ALLEN DNAME DEPTNO ------------ -----ACCOUNTING 10 RESEARCH 20 SALES 30 RESEARCH 20 SALES 30 OPERATIONS 40 Equivalent Oracle join statement SELECT ename,dname,dept.deptno FROM empa,dept WHERE dept.deptno = emp.deptno(+); Carl Dudley – University of Wolverhampton 10 LEFT Outer Joins SELECT ename,dname,dept.deptno FROM empa LEFT OUTER JOIN dept ON empa.deptno = dept.deptno; ENAME ------CLARK SCOTT TURNER FORD ALLEN EXTRA DNAME DEPTNO ------------ -----ACCOUNTING 10 RESEARCH 20 SALES 30 RESEARCH 20 SALES 30 Equivalent Oracle join statement SELECT ename,dname,dept.deptno FROM empa, dept WHERE dept.deptno(+) = empa.deptno; Carl Dudley – University of Wolverhampton 11 FULL Outer Joins SELECT ename,dname,dept.deptno d_deptno, empa.deptno e_deptno FROM empa FULL OUTER JOIN dept ON empa.deptno = dept.deptno; ENAME ------CLARK SCOTT TURNER FORD ALLEN EXTRA DNAME D_DEPTNO E_DEPTNO ------------ -------- -------ACCOUNTING 10 10 RESEARCH 20 20 SALES 30 30 RESEARCH 20 20 SALES 30 30 OPERATIONS All rows included from both tables 40 Equivalent (ILLEGAL) Oracle join statement SELECT ename,dname,dept.deptno,empa.deptno FROM empa, dept WHERE dept.deptno(+) = empa.deptno(+); Carl Dudley – University of Wolverhampton 12 FULL OUTER JOIN – Oracle11g Oracle now performs a 'NATIVE' full outer join SELECT ename ,dname FROM empa e FULL OUTER JOIN dept d ON e.deptno = d.deptno; --------------------------------------------------------------| Id | Operation | Name |Rows |Bytes |Cost(%CPU --------------------------------------------------------------| 0| SELECT STATEMENT | | 15 | 240 | 7 (15 | 1| VIEW | VW_FOJ_0 | 15 | 240 | 7 (15 |* 2| HASH JOIN FULL OUTER| | 15 | 330 | 7 (15 | 3| TABLE ACCESS FULL | DEPT | 4 | 52 | 3 (0 | 4| TABLE ACCESS FULL | EMPA | 14 | 126 | 3 (0 --------------------------------------------------------------- Carl Dudley – University of Wolverhampton 13 FULL OUTER JOIN – Oracle10g ALTER SESSION SET optimizer_features_enable = '10.2.0.1'; SELECT ename ,dname FROM empa e FULL OUTER JOIN dept d ON e.deptno = d.deptno; -----------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost | -----------------------------------------------------------| 0 | SELECT STATEMENT | | 15 | 240 | 13| | 1 | VIEW | | 15 | 240 | 13| | 2 | UNION-ALL | | | | | |* 3 | HASH JOIN OUTER | | 14 | 308 | 7| | 4 | TABLE ACCESS FULL| EMPA | 14 | 126 | 3| | 5 | TABLE ACCESS FULL| DEPT | 4 | 52 | 3| |* 6 | HASH JOIN ANTI | | 1 | 16 | 7| | 7 | TABLE ACCESS FULL| DEPT | 4 | 52 | 3| | 8 | TABLE ACCESS FULL| EMPA | 14 | 42 | 3| -----------------------------------------------------------Carl Dudley – University of Wolverhampton 14 FULL OUTER JOIN – Oracle10g (continued) Statement is transformed to a UNION construct SELECT ename ,dname FROM empa e ,dept d WHERE e.deptno = d.deptno(+) UNION ALL SELECT null ,dname FROM dept d2 WHERE NOT EXISTS (SELECT 'x' FROM empa e2 WHERE e2.deptno = d2.deptno); ― Generates same execution plan as for 10g FULL OUTER JOIN Native full outer join available in 10.2.0.3 and 10.2.0.4 with a hint /*+NATIVE_FULL_OUTER_JOIN */ Undocumented parameter _optimizer_native_full_outer_join Carl Dudley – University of Wolverhampton 15 Oracle Join Techniques ANSI and Oracle Joins Two-way Outer Joins Join and Filter Conditions Chaining on the Outer Join Hash Join Trees Anti Joins and Semi Joins Lateral Joins Nested Loops Joins Join Elimination Carl Dudley – University of Wolverhampton 16 Two-way Outer Joins project table linked to a cut down modified version of emp, called empb ― Project number 3 (DESIGN) has no employees empb EMPNO ----7782 7788 7844 7499 ENAME -----CLARK SCOTT TURNER ALLEN JOB -------MANAGER ANALYST SALESMAN SAlESMAN MGR ---7839 7566 7698 7698 HIREDATE ----------09-JUN-1981 19-APR-1987 08-SEP-1981 20-FEB-1981 dept proj PROJ_ID ------1 2 3 SAL COMM DEPTNO PROJ_ID ---- ---- ------ ------2450 10 1 3000 20 2 1500 0 30 1 1600 300 30 1 PNAME --------BPR MIGRATION DESIGN START_DATE ----------01-JUL-2002 12-OCT-2002 01-NOV-2002 DEPTNO ------10 20 30 40 DNAME ---------ACCOUNTING RESEARCH SALES OPERATIONS Carl Dudley – University of Wolverhampton LOC -------NEW YORK DALLAS CHICAGO BOSTON 17 Two-way Outer Joins Show details of employees with their projects and departments — Include projects with no employees and departments with no employees project empb (+) dept (+) Carl Dudley – University of Wolverhampton 18 ANSI Two-way Outer Joins – Expected result Two-way outer joins are allowed but the result may not be as expected Outer join of empb to both dept and project based on deptno and proj_id values (as requested on the previous slide) should give the following result ENAME ---------ALLEN TURNER CLARK SCOTT HIREDATE DEPTNO DNAME PROJ_ID PNAME ----------- ------ ----------- ------- --------20-FEB-1981 30 SALES 1 BPR 08-SEP-1981 30 SALES 1 BPR 09-JUN-1981 10 ACCOUNTING 1 BPR 19-APR-1987 20 RESEARCH 2 MIGRATION 40 OPERATIONS 3 DESIGN Carl Dudley – University of Wolverhampton 19 ANSI Two-way Outer Joins – Missing Rows Unexpected results? SELECT ename, hiredate,d.deptno,dname,p.proj_id,pname FROM dept d LEFT OUTER JOIN empb e ON e.deptno = d.deptno RIGHT OUTER JOIN proj p ON e.proj_id = p.proj_id; ENAME ---------CLARK SCOTT ALLEN TURNER HIREDATE DEPTNO DNAME PROJ_ID PNAME ----------- ------ ----------- ------- --------09-JUN-1981 10 ACCOUNTING 1 BPR 19-APR-1987 20 RESEARCH 2 MIGRATION 20-FEB-1981 30 SALES 1 BPR 08-SEP-1981 30 SALES 1 BPR 3 DESIGN Carl Dudley – University of Wolverhampton 20 ANSI Two-way Outer Joins – Missing Rows (continued) Reordering the joins still gives another different unexpected result? ― Outer joins are not 'symmetrical' SELECT ename, hiredate,d.deptno,dname,p.proj_id,pname FROM proj p LEFT OUTER JOIN empb e ON e.proj_id = p.proj_id RIGHT OUTER JOIN dept d ON e.deptno = d.deptno; ENAME ---------CLARK SCOTT TURNER ALLEN HIREDATE DEPTNO DNAME PROJ_ID PNAME ----------- ------ ----------- ------- --------09-JUN-1981 10 ACCOUNTING 1 BPR 19-APR-1987 20 RESEARCH 2 MIGRATION 08-SEP-1981 30 SALES 1 BPR 20-FEB-1981 30 SALES 1 BPR 40 OPERATIONS Carl Dudley – University of Wolverhampton 21 ANSI Two-way Outer Joins - Explanation Explanation of unexpected behaviour — Examine the result of the first join in the first example — The fifth row does not have a value in the proj_id column — This row can not take part in the final join with the proj table SELECT ename, hiredate,d.deptno,dname,proj_id FROM dept d LEFT OUTER JOIN empb e ON e.deptno = d.deptno; ENAME ---------CLARK SCOTT TURNER ALLEN HIREDATE DEPTNO DNAME PROJ_ID ----------- ------ ----------- ------09-JUN-1981 10 ACCOUNTING 1 19-APR-1987 20 RESEARCH 2 08-SEP-1981 30 SALES 1 20-FEB-1981 30 SALES 1 40 OPERATIONS Carl Dudley – University of Wolverhampton 22 ANSI Two-way Outer Joins – use of FULL Outer joining dept to empb gives a row with NULL in proj_id ― This row can not take part in the second outer join ― The second join needs to be a FULL OUTER JOIN SELECT ename,hiredate,d.deptno,dname,p.proj_id,pname FROM dept d LEFT OUTER JOIN empb e ON e.deptno = d.deptno FULL OUTER JOIN proj p ON e.proj_id = p.proj_id; ENAME ---------ALLEN TURNER CLARK SCOTT HIREDATE DEPTNO DNAME PROJ_ID PNAME ----------- ------ ----------- ------- --------20-FEB-1981 30 SALES 1 BPR 08-SEP-1981 30 SALES 1 BPR 09-JUN-1981 10 ACCOUNTING 1 BPR 19-APR-1987 20 RESEARCH 2 MIGRATION 40 OPERATIONS 3 DESIGN Carl Dudley – University of Wolverhampton 23 Two-way Outer Joins – Oracle Style In 11g, Oracle syntax cannot outer join a table to more than one other table SELECT ename,hiredate,d.deptno,dname,p.proj_id,pname FROM dept d, empb e, proj p WHERE e.deptno(+) = d.deptno AND e.proj_id(+) = p.proj_id; ORA-01417: a table may be outer joined to at most one other table Carl Dudley – University of Wolverhampton 24 Two-way Outer Joins – Oracle Style (continued) But in Oracle12c, this would be the output ― Cannot be imitated using ANSI syntax ENAME ---------SCOTT ALLEN TURNER CLARK HIREDATE DEPTNO DNAME PROJ_ID PNAME ----------- ------ ----------- ------- ---------19-APR-1987 20 RESEARCH 2 MIGRATION 20-FEB-1981 30 SALES 1 BPR 08-SEP-1981 30 SALES 1 BPR 09-JUN-1981 10 ACCOUNTING 1 BPR 40 OPERATIONS 1 BPR 40 OPERATIONS 2 MIGRATION 40 OPERATIONS 3 DESIGN 30 SALES 2 MIGRATION 30 SALES 3 DESIGN 20 RESEARCH 1 BPR 20 RESEARCH 3 DESIGN 10 ACCOUNTING 2 MIGRATION 10 ACCOUNTING 3 DESIGN Carl Dudley – University of Wolverhampton 25 Oracle Outer Joins with Subqueries Show each department with its longest serving employee — Subqueries are not allowed in combination with an outer join condition SELECT ename, hiredate,d.deptno,dname FROM dept d, d LEFT JOIN emp e empaOUTER e ON e.deptno = d.deptno WHERE e.deptno(+) = d.deptno AND e.hiredate(+) e.hiredate = (SELECT MIN(e.hiredate) = (SELECT MIN(e.hiredate) FROM empempa e FROM e WHERE e.deptno = d.deptno); WHERE e.deptno = d.deptno); ORA-01799: a column may not be outer-joined to a subquery What about ANSI joins? Carl Dudley – University of Wolverhampton 26 Oracle Join Techniques ANSI and Oracle Joins Two-way Outer Joins Join and Filter Conditions Chaining on the Outer Join Hash Join Trees Anti Joins and Semi Joins Lateral Joins Nested Loops Joins Join Elimination Carl Dudley – University of Wolverhampton 27 Join and Filter Conditions Oracle uses the ON clause for join conditions Conditions specified in a WHERE clause are treated as filter conditions Filter conditions can also be specified in the ON (or USING) clause Join operations and conditions are effectively processed before the WHERE clause conditions Carl Dudley – University of Wolverhampton 28 Oracle Join and Filter Conditions SELECT dept.deptno,dname,ename,job FROM dept, empa WHERE empa.deptno(+) = dept.deptno AND empa.job = 'SALESMAN'; DEPTNO -----30 30 DNAME ----------SALES SALES ENAME -------TURNER ALLEN Filter applied after the join JOB -------SALESMAN SALESMAN SELECT dept.deptno,dname,ename,job FROM dept, empa WHERE empa.deptno(+) = dept.deptno AND empa.job(+) = 'SALESMAN'; DEPTNO -----10 20 30 30 40 DNAME ----------ACCOUNTING RESEARCH SALES SALES OPERATIONS ENAME JOB -------- -------TURNER ALLEN Filter applied during the join — Somewhat awkward syntax SALESMAN SALESMAN Carl Dudley – University of Wolverhampton 29 ANSI Join and Filter Conditions SELECT dept.deptno,dname,ename,job FROM dept LEFT OUTER JOIN empa ON empa.deptno = dept.deptno WHERE empa.job = 'SALESMAN‘; DEPTNO -----30 30 DNAME ---------SALES SALES ENAME -------ALLEN TURNER JOB -------SALESMAN SALESMAN Filter applied after the join — Easier to understand due to separation of join conditions from filter conditions SELECT dept.deptno,dname,ename,job FROM dept LEFT OUTER JOIN empa ON empa.deptno = dept.deptno AND empa.job = 'SALESMAN'; DEPTNO -----30 30 40 20 10 DNAME ----------SALES SALES OPERATIONS RESEARCH ACCOUNTING ENAME ------TURNER ALLEN JOB -------SALESMAN SALESMAN Filter applied during the join Note the three outer joined rows - one row for each department having no salesmen Carl Dudley – University of Wolverhampton 30 Oracle Outer Joins and OR Oracle syntax cannot cope SELECT dname ,ename ,job ,loc ,sal FROM emp e ,dept d WHERE e.deptno(+) = d.deptno AND (sal(+) < 1000 OR loc(+) = 'DALLAS') ORDER BY dname; AND (sal(+) < 1000 OR loc(+) = 'DALLAS') * ERROR : ORA-01719:outer join operator (+) not allowed in operand of OR or IN Carl Dudley – University of Wolverhampton 31 ANSI Outer Joins and OR ANSI join handles OR with outer join SELECT dname ,ename ,job ,loc ,sal FROM emp e RIGHT OUTER JOIN dept d ON e.deptno = d.deptno AND (sal < 1000 OR loc = 'DALLAS') ORDER BY dname; DNAME -------------ACCOUNTING OPERATIONS RESEARCH RESEARCH RESEARCH RESEARCH RESEARCH SALES ENAME JOB LOC ---------- --------- ------------NEW YORK BOSTON ADAMS CLERK DALLAS FORD ANALYST DALLAS JONES MANAGER DALLAS SMITH CLERK DALLAS SCOTT ANALYST DALLAS JAMES CLERK CHICAGO Carl Dudley – University of Wolverhampton SAL ---1100 3000 2975 800 3000 950 32 Oracle Join Techniques ANSI and Oracle Joins Two-way Outer Joins Join and Filter Conditions Chaining on the Outer Join Hash Join Trees Anti Joins and Semi Joins Lateral Joins Nested Loops Joins Join Elimination Carl Dudley – University of Wolverhampton 33 'Chaining on' the Outer Join course attendance student All courses have attendances, all attendances have offerings ― Hence outer join is never necessary when joining offering and attendance Some students do not have attendances Query : Show ALL students along with their courses Carl Dudley – University of Wolverhampton 34 Data in the Sample Tables course COURSE_ID START_DATE --------- ---------1001 14-DEC-11 1002 12-JUL-12 1003 20-NOV-12 STUDENT_ID ---------1111 2299 4568 5556 6789 attendance COURSE_ID STUDENT_ID --------- ---------1001 1111 1002 2299 1003 2299 1002 6789 1003 1111 STUDENT_LNAME student ------------BROWN ADAMS COX TYLER ROSE Two students do not have any attendances All courses and attendances are related Carl Dudley – University of Wolverhampton 35 Joining course and attendance SELECT c.course_id c_course_id ,a.course_id a_course_id ,a.student_id FROM course c INNER JOIN attendance a ON c.course_id = a.course_id; SELECT o.course_id c_course_id ,a.course_id a_course_id ,a.student_id a_student_id FROM attendance a LEFT OUTER JOIN course c ON a.course_id = c.course_id; C_COURSE_ID A_COURSE_ID A_STUDENT_ID ----------- ----------- -----------1001 1001 1111 1002 1002 2299 1003 1003 2299 1002 1002 6789 1003 1003 1111 Outer join is completely unnecessary as all rows match Carl Dudley – University of Wolverhampton 36 Joining attendance and student Outer join is necessary to include students without attendances SELECT s.student_id s_student_id ,s.student_lname s_student_lname ,a.student_id a_student_id ,a.course_id a_course_id FROM student s LEFT OUTER JOIN attendance a ON s.student_id = a.student_id; S_STUDENT_ID -----------1111 2299 2299 6789 1111 4568 5556 S_LNAME A_STUDENT_ID A_COURSE_ID ------- ------------ ----------BROWN 1111 1001 ADAMS 2299 1002 ADAMS 2299 1003 ROSE 6789 1002 BROWN 1111 1003 COX TYLER Carl Dudley – University of Wolverhampton 37 Join Three Tables - Inner join 'loses' students SELECT s.student_id s_student_id,s.student_lname s_lname ,a.student_id a_student_id,a.course_id a_course_id ,c.course_id c_course_id,c.start_date FROM student s LEFT OUTER JOIN attendance a ON s.student_id = a.student_id INNER JOIN course c ON c.course_id = a.course_id; S_STUDENT_ID -----------1111 2299 2299 6789 1111 S_LNAME A_STUDENT_ID A_COURSE_ID C_COURSE_ID START_DATE ------- ------------ ----------- ----------- ---------BROWN 1111 1001 1001 14-DEC-11 ADAMS 2299 1002 1002 12-JUL-12 ADAMS 2299 1003 1003 20-NOV-12 ROSE 6789 1002 1002 12-JUL-12 BROWN 1111 1003 1003 20-NOV-12 ----------------------------------------------| Id | Operation | Name |Rows | ----------------------------------------------| 0| SELECT STATEMENT | | 5| |* 1| HASH JOIN | | 5| |* 2| HASH JOIN | | 5| | 3| TABLE ACCESS FULL| COURSE | 3| | 4| TABLE ACCESS FULL| ATTENDANCE | 5| | 5| TABLE ACCESS FULL | STUDENT | 5| ----------------------------------------------- Rows are lost by the inner join Oracle is smart enough not to perform the outer join Carl Dudley – University of Wolverhampton 38 Chaining on the OUTER JOIN SELECT s.student_id s_student_id,s.student_lname s_lname ,a.student_id a_student_id,a.course_id a_course_id ,c.course_id c_course_id,c.start_date FROM student s LEFT OUTER JOIN attendance a ON s.student_id = a.student_id LEFT OUTER JOIN course c ON c.course_id = a.course_id; S_STUDENT_ID -----------1111 2299 2299 6789 1111 4568 5556 S_LNAME A_STUDENT_ID A_COURSE_ID C_COURSE_ID START_DATE ------- ------------ ----------- ----------- ---------BROWN 1111 1001 1001 14-DEC-11 ADAMS 2299 1002 1002 12-JUL-12 ADAMS 2299 1003 1003 20-NOV-12 ROSE 6789 1002 1002 12-JUL-12 BROWN 1111 1003 1003 20-NOV-12 COX TYLER ----------------------------------------------| Id | Operation | Name |Rows | ----------------------------------------------| 0| SELECT STATEMENT | | 5| |* 1| HASH JOIN OUTER | | 5| |* 2| HASH JOIN OUTER | | 5| | 3| TABLE ACCESS FULL| STUDENT | 5| | 4| TABLE ACCESS FULL| ATTENDANCE | 5| | 5| TABLE ACCESS FULL | COURSE | 3| ----------------------------------------------- Outer join performed between attendance and course when not strictly necessary Carl Dudley – University of Wolverhampton 39 Avoiding the second OUTER JOIN SELECT s.student_id s_student_id,s.student_lname s_lname ,a.student_id a_student_id,a.course_id a_course_id ,c.course_id c_course_id,c.start_date FROM course c JOIN attendance a ON c.course_id = a.course_id RIGHT OUTER JOIN student s ON s.student_id = a.student_id; S_STUDENT_ID -----------1111 2299 2299 6789 1111 4568 5556 S_LNAME A_STUDENT_ID A_COURSE_ID C_COURSE_ID START_DATE ------- ------------ ----------- ----------- ---------BROWN 1111 1001 1001 14-DEC-11 ADAMS 2299 1002 1002 12-JUL-12 ADAMS 2299 1003 1003 20-NOV-12 ROSE 6789 1002 1002 12-JUL-12 BROWN 1111 1003 1003 20-NOV-12 COX TYLER -----------------------------------------------| Id | Operation | Name |Rows | -----------------------------------------------| 0| SELECT STATEMENT | | 5| |* 1| HASH JOIN OUTER | | 5| | 2| TABLE ACCESS FULL | STUDENT | 5| | 3| VIEW | | 5| |* 4| HASH JOIN | | 5| | 5| TABLE ACCESS FULL| COURSE | 3| | 6| TABLE ACCESS FULL| ATTENDANCE | 5| ------------------------------------------------ Inner join performed first Outer join preserves all student rows Carl Dudley – University of Wolverhampton 40 Ordering the joins 'Right' SELECT s.student_id s_student_id,s.student_lname s_lname ,a.student_id a_student_id,a.course_id a_course_id ,c.course_id c_course_id,c.start_date FROM attendance a RIGHT OUTER JOIN student s ON s.student_id = a.student_id JOIN course c ON c.course_id = a.course_id; S_STUDENT_ID -----------1111 2299 2299 6789 1111 S_LNAME A_STUDENT_ID A_COURSE_ID C_COURSE_ID START_DATE ------- ------------ ----------- ----------- ---------BROWN 1111 1001 1001 14-DEC-11 ADAMS 2299 1002 1002 12-JUL-12 ADAMS 2299 1003 1003 20-NOV-12 ROSE 6789 1002 1002 12-JUL-12 BROWN 1111 1003 1003 20-NOV-12 ----------------------------------------------| Id | Operation | Name |Rows | ----------------------------------------------| 0| SELECT STATEMENT | | 5| |* 1 HASH JOIN | | 5| |* 2| HASH JOIN | | 5| | 3| TABLE ACCESS FULL| COURSE | 3| | 4| TABLE ACCESS FULL| ATTENDANCE | 5| | 5| TABLE ACCESS FULL | STUDENT | 5| ----------------------------------------------- Right join would be performed first? Inner join would then lose the outer joined student rows No outer joins performed Carl Dudley – University of Wolverhampton 41 Oracle Join Techniques ANSI and Oracle Joins Two-way Outer Joins Join and Filter Conditions Chaining on the Outer Join Hash Join Trees Anti Joins and Semi Joins Lateral Joins Nested Loops Joins Join Elimination Carl Dudley – University of Wolverhampton 42 Processing a Hash Join Build Table (customers) NAME CITY ... SCOTT BATH ... PAYNE YORK ... FOX LEEDS ... SMITH ELY ... WOOD BATH ... ADAMS LONDON ... ORD_ID NAME ... 1 SMITH ... 2 PAYNE ... 3 FOX ... 4 SCOTT ... 5 WOOD ... 6 ADAMS ... ADAMS LONDON ... FOX LEEDS ... PAYNE YORK ... SCOTT BATH ... WOOD BATH ... Hash table SMITH ELY ... Probe Table (orders) Carl Dudley – University of Wolverhampton 43 Join Trees for T1 T2 T3 T4 Left deep tree Right deep tree Hash table built on T4 probed by result of T1 join T2 join T3 Output of T1 join T2 join T3 probed by T4 Output of T1 join T2 probed by T3 T4 Hash table built on T1 probed by T2 T1 T3 T2 Hash table built on T3 probed by result of T1 join T2 T4 Hash table built on T2 probed by T1 T3 T2 Carl Dudley – University of Wolverhampton T1 44 Join Trees for T1 T2 T3 T4 (continued) Zig-zag tree Bushy tree T4 T3 T1 T2 T3 T4 T1 Carl Dudley – University of Wolverhampton T2 45 Summary of Hash Join Trees Left-deep ― Result sets are formed before build of next hash table ― Workarea discarded after each subsequent join ― Only one workarea used Right-deep ― Hash tables on T3 and T4 can be built 'in parallel' with hash table on T1 ― Three workareas can be used ― Could be useful when the results of joins are larger than the two sets of rows being joined Carl Dudley – University of Wolverhampton 46 Tree Combinations Optimizer normally considers only left-deep trees ― Left deep joins cover most requirements ― Number of left-deep trees = n! ― Total number of join trees = (2n-2)!/(n-1)! Tables Left-Deep Trees Bushy Trees (inc. Left and Right) 1 1 1 2 2 2 3 6 12 4 24 120 5 120 1,680 6 720 30,240 Can Oracle be forced to perform a bushy tree? Carl Dudley – University of Wolverhampton 47 Four Table Join Scenario sa ID -1 2 3 : wa NAME WA_ID ---- ----x 1 y 2 z 3 : : WA_ID ----1 2 3 : WA_NAME ------name1 name2 name3 : p pt P_ID ---1 2 3 : P_NAME WA_ID PT_ID ------ ----- ----pname1 1 1 pname2 2 2 pname3 3 3 : : : PT_ID ----1 2 3 : Carl Dudley – University of Wolverhampton PT_NAME ------ptname1 ptname2 ptname3 : 48 Right Deep Join Tree Oracle uses hints internally to force a right deep join in this case SELECT /*+GATHER_PLAN_STATISTICS */ name FROM sa JOIN wa ON wa.wa_id = sa.wa_id JOIN p ON wa.wa_id = p.wa_id JOIN pt ON pt.pt_id = p.pt_id; SWAP_JOIN_INPUTS(@"SEL$EE94F965" "PT"@"SEL$3") SWAP_JOIN_INPUTS(@"SEL$EE94F965" "WA"@"SEL$1") SWAP_JOIN_INPUTS(@"SEL$EE94F965" "SA"@"SEL$1") Internally generated hints ----------------------------| SELECT STATEMENT | | | HASH JOIN | | | TABLE ACCESS FULL | SA | | HASH JOIN | | | TABLE ACCESS FULL | WA | | HASH JOIN | | | TABLE ACCESS FULL| PT | | TABLE ACCESS FULL| P | ----------------------------Carl Dudley – University of Wolverhampton 49 Left Deep Join Tree Left deep tree can be forced using hints SELECT /*+GATHER_PLAN_STATISTICS no_swap_join_inputs(wa) no_swap_join_inputs(p) no_swap_join_inputs(pt) no_swap_join_inputs(sa)*/ name FROM sa JOIN wa ON wa.wa_id = sa.wa_id JOIN p ON wa.wa_id = p.wa_id JOIN pt ON pt.pt_id = p.pt_id; ----------------------------| SELECT STATEMENT | | | HASH JOIN | | | HASH JOIN | | | HASH JOIN | | | TABLE ACCESS FULL| PT | | TABLE ACCESS FULL| P | | TABLE ACCESS FULL | WA | | TABLE ACCESS FULL | SA | ----------------------------Carl Dudley – University of Wolverhampton 50 Forcing a Bushy Tree In complex decision support scenarios a bushy tree can be a good plan ― Cannot be forced using '(', ')' or ORDERED, LEADING or other 'conventional' hints ― Must use inline views and a selection of less well known hints to stop Oracle merging the views internally SELECT /*+no_merge(v1) no_merge(v2)*/ name FROM (SELECT sa.name ,wa.wa_id ----------------------------FROM sa JOIN wa | | ON wa.wa_id = sa.wa_id) v1 | SELECT STATEMENT | HASH JOIN | | JOIN | VIEW | | (SELECT p.wa_id | HASH JOIN | | FROM p JOIN pt | TABLE ACCESS FULL| PT | ON pt.pT_id = p.pT_id) v2 | TABLE ACCESS FULL| P | ON v1.wa_id = v2.wa_id; | VIEW | | | HASH JOIN | | | TABLE ACCESS FULL| WA | | TABLE ACCESS FULL| SA | ----------------------------Carl Dudley – University of Wolverhampton 51 Oracle Join Techniques ANSI and Oracle Joins Two-way Outer Joins Join and Filter Conditions Chaining on the Outer Join Hash Join Trees Anti Joins and Semi Joins Lateral Joins Nested Loops Joins Join Elimination Carl Dudley – University of Wolverhampton 52 Hash Join Plans Semi-joins ― Often occur with EXISTS and IN subqueries ― Used when existence tests are required Find departments which have employees ― Semi-join returns a department only once no matter how many employees work for it SELECT * FROM dept WHERE EXISTS (SELECT 'x' FROM emp WHERE deptno = dept.deptno); Carl Dudley – University of Wolverhampton 53 Right Semi Join From Oracle 10g, the driving table can be automatically switched ― Can depend on size of input rowsets ― SWAP_JOIN_INPUTS hint is used internally • Often used to avoid high memory usage (monitor OMEM with dbms_xplan) dept : 4 rows emp : 7168 rows dept : 8192 rows emp : 7168 rows ------------------------------------|Operation |Name |Rows | ------------------------------------|SELECT STATEMENT | |8192 | | HASH JOIN RIGHT SEMI| |8192 | | VIEW |VW_SQ_1|7168 | | TABLE ACCESS FULL |EMP |7168 | | TABLE ACCESS FULL |DEPT |8192 | ------------------------------------- ----------------------------------|Operation |Name |Rows| ----------------------------------|SELECT STATEMENT | | 4| | HASH JOIN SEMI | | 4| | TABLE ACCESS FULL |DEPT | 4| | VIEW |VW_SQ_1|7168| | TABLE ACCESS FULL|EMP |7168| ----------------------------------- Carl Dudley – University of Wolverhampton 54 Departments with no Employees SELECT * FROM dept WHERE deptno NOT IN (SELECT deptno FROM emp); SELECT * FROM dept x WHERE NOT EXISTS (SELECT 1 FROM emp y WHERE y.deptno = x.deptno); DEPTNO DNAME LOC ------ ---------- -----40 OPERATIONS BOSTON Carl Dudley – University of Wolverhampton 55 No Index and no NOT NULL Constraint on emp.deptno Oracle Version NOT IN plan NOT EXISTS plan 8i SELECT STATEMENT FILTER TABLE ACCESS FULL DEPT TABLE ACCESS FULL EMP SELECT STATEMENT FILTER TABLE ACCESS FULL DEPT TABLE ACCESS FULL EMP 9i SELECT STATEMENT FILTER TABLE ACCESS FULL DEPT TABLE ACCESS FULL EMP SELECT STATEMENT HASH JOIN ANTI TABLE ACCESS FULL DEPT TABLE ACCESS FULL EMP 10g SELECT STATEMENT FILTER TABLE ACCESS FULL DEPT TABLE ACCESS FULL EMP SELECT STATEMENT HASH JOIN ANTI TABLE ACCESS FULL DEPT TABLE ACCESS FULL EMP 11g SELECT STATEMENT HASH JOIN ANTI NA TABLE ACCESS FULL DEPT TABLE ACCESS FULL EMP SELECT STATEMENT HASH JOIN ANTI TABLE ACCESS FULL DEPT TABLE ACCESS FULL EMP Carl Dudley – University of Wolverhampton 56 NOT NULL constraint on emp.deptno Oracle Version NOT IN plan NOT EXISTS plan 8i SELECT STATEMENT FILTER TABLE ACCESS FULL DEPT TABLE ACCESS FULL EMP SELECT STATEMENT FILTER TABLE ACCESS FULL DEPT TABLE ACCESS FULL EMP 9i SELECT STATEMENT FILTER TABLE ACCESS FULL DEPT TABLE ACCESS FULL EMP SELECT STATEMENT HASH JOIN ANTI TABLE ACCESS FULL DEPT TABLE ACCESS FULL EMP 10g SELECT STATEMENT FILTER TABLE ACCESS FULL DEPT TABLE ACCESS FULL EMP SELECT STATEMENT HASH JOIN ANTI TABLE ACCESS FULL DEPT TABLE ACCESS FULL EMP 11g SELECT STATEMENT HASH JOIN ANTI SNA TABLE ACCESS FULL DEPT TABLE ACCESS FULL EMP SELECT STATEMENT HASH JOIN ANTI TABLE ACCESS FULL DEPT TABLE ACCESS FULL EMP Carl Dudley – University of Wolverhampton 57 Index on emp.deptno, no NOT NULL constraint Oracle Version NOT IN plan NOT EXISTS plan 8i SELECT STATEMENT FILTER TABLE ACCESS FULL DEPT TABLE ACCESS FULL EMP SELECT STATEMENT FILTER TABLE ACCESS FULL DEPT INDEX RANGE SCAN EMP$DEPTNO 9i SELECT STATEMENT FILTER TABLE ACCESS FULL DEPT TABLE ACCESS FULL EMP SELECT STATEMENT FILTER TABLE ACCESS FULL DEPT INDEX RANGE SCAN EMP$DEPTNO 10g SELECT STATEMENT FILTER TABLE ACCESS FULL DEPT TABLE ACCESS FULL EMP SELECT STATEMENT NESTED LOOPS ANTI TABLE ACCESS FULL DEPT INDEX RANGE SCAN EMP$DEPTNO 11g SELECT STATEMENT HASH JOIN ANTI NA TABLE ACCESS FULL DEPT TABLE ACCESS FULL EMP SELECT STATEMENT HASH JOIN ANTI TABLE ACCESS FULL DEPT INDEX FAST FULL SCAN EMP$DEPTNO Carl Dudley – University of Wolverhampton 58 Index and NOT NULL Constraint on emp.deptno Version NOT IN plan NOT EXISTS plan 8i SELECT STATEMENT FILTER TABLE ACCESS FULL DEPT INDEX RANGE SCAN EMP$DEPTNO SELECT STATEMENT FILTER TABLE ACCESS FULL DEPT INDEX RANGE SCAN EMP$DEPTNO 9i SELECT STATEMENT FILTER TABLE ACCESS FULL DEPT INDEX FULL SCAN EMP$DEPTNO SELECT STATEMENT FILTER TABLE ACCESS FULL DEPT INDEX RANGE SCAN EMP$DEPTNO 10g SELECT STATEMENT FILTER TABLE ACCESS FULL DEPT INDEX FULL SCAN EMP$DEPTNO SELECT STATEMENT NESTED LOOPS ANTI TABLE ACCESS FULL DEPT INDEX RANGE SCAN EMP$DEPTNO 11g SELECT STATEMENT HASH JOIN ANTI SNA TABLE ACCESS FULL DEPT INDEX FULL SCAN EMP$DEPTNO SELECT STATEMENT NESTED LOOPS ANTI TABLE ACCESS FULL DEPT INDEX RANGE SCAN EMP$DEPTNO If the column on the right hand side of the condition (emp.deptno) has no NOT NULL constraint, then NA is used — If it is declared NOT NULL, SNA is used, along with an available index Carl Dudley – University of Wolverhampton 59 Oracle Join Techniques ANSI and Oracle Joins Two-way Outer Joins Join and Filter Conditions Chaining on the Outer Join Hash Join Trees Anti Joins and Semi Joins Lateral Joins Nested Loops Joins Join Elimination Carl Dudley – University of Wolverhampton 60 Lateral Joins Inline views cannot reference columns outside of the view ― Considered to be out of scope SELECT dname ,ename FROM dept d ,(SELECT ename FROM emp e WHERE e.deptno = d.deptno); WHERE e.deptno = d.deptno) * ERROR : ORA-00904: "D"."DEPTNO": invalid identifier Lateral views allow such references ― Used internally Similar to correlated subqueries Carl Dudley – University of Wolverhampton 61 Lateral Joins in Oracle12c SELECT dname ,ename FROM dept d ,LATERAL(SELECT ename FROM emp e WHERE e.deptno = d.deptno); DNAME -------------RESEARCH SALES SALES : Identical execution plan to equivalent equi-join ENAME ---------SMITH ALLEN WARD : Need to set an event on Oracle11g ― LATERAL keyword can then be used to allow correlation ALTER SESSION SET EVENTS '22829 TRACE NAME CONTEXT FOREVER'; Carl Dudley – University of Wolverhampton 62 Lateral Outer Join Syntax SELECT dname ,ename ,job ,loc ,sal FROM dept ,LATERAL(SELECT ename,job,sal FROM emp WHERE emp.deptno = dept.deptno AND (sal < 1000 OR job = 'ANALYST'))(+); DNAME -------------ACCOUNTING RESEARCH RESEARCH RESEARCH SALES OPERATIONS ENAME JOB LOC SAL ---------- --------- ------------- ---------NEW YORK SMITH CLERK DALLAS 800 SCOTT ANALYST DALLAS 3000 FORD ANALYST DALLAS 3000 JAMES CLERK CHICAGO 950 BOSTON Carl Dudley – University of Wolverhampton 63 CROSS APPLY and OUTER APPLY Compatibility issues with SQL Server migration tools SELECT dname,ename,job,loc,sal FROM dept CROSS APPLY (SELECT ename,job,sal FROM emp WHERE emp.deptno = dept.deptno AND (sal < 1000 OR job = 'ANALYST')) SELECT dname,ename,job,loc,sal FROM dept OUTER APPLY (SELECT ename,job,sal FROM emp WHERE emp.deptno = dept.deptno AND (sal < 1000 OR job = 'ANALYST')) Carl Dudley – University of Wolverhampton 64 Equivalent Outer Join Plans SELECT dname,ename,job,loc,sal FROM dept OUTER APPLY (SELECT ename,job,sal FROM emp WHERE emp.deptno = dept.deptno AND (sal < 1000 OR job = 'ANALYST')) SELECT dname,ename,job,loc,sal FROM dept, emp WHERE emp.deptno(+) = dept.deptno AND (sal(+) < 1000 OR job(+) = 'ANALYST') SELECT dname,ename,job,loc,sal FROM dept ,LATERAL(SELECT ename,job,sal FROM emp WHERE emp.deptno = dept.deptno AND (sal < 1000 OR job = 'ANALYST'))(+); ------------------------------------------| Id | Operation | Name | Rows | ------------------------------------------| 0 | SELECT STATEMENT | | 5 | |* 1 | HASH JOIN OUTER | | 5 | | 2 | TABLE ACCESS FULL| DEPT | 4 | |* 3 | TABLE ACCESS FULL| EMP | 4 | ------------------------------------------Carl Dudley – University of Wolverhampton 65 Use of CROSS/OUTER APPLY When join sets are not known in advance Example purely for illustration : Number of emp rows to join is governed by highest salary in that department ― Note use of subquery in FETCH clause • Can use any appropriate variable or expression SELECT deptno ,empno ,ename ,sal FROM dept OUTER APPLY (SELECT empno ,ename ,sal FROM emp WHERE emp.deptno = dept.deptno order by sal desc FETCH FIRST (SELECT MAX(sal)/1500 FROM emp WHERE emp.deptno = dept.deptno) ROWS ONLY) ORDER BY dept.deptno; Carl Dudley – University of Wolverhampton 66 CROSS/OUTER APPLY with Table level functions CREATE TYPE emp_row_type as OBJECT ( empno VARCHA2R(8), ename VARCHAR2(20), deptno VARCHAR2(20)); CREATE TYPE emp_table_type as TABLE OF emp_row_type; CREATE OR REPLACE FUNCTION get_all_emps(pi_deptno in number) RETURN emp_table_type PIPELINED AS BEGIN FOR cur IN (SELECT * FROM emp where deptno = pi_deptno) LOOP PIPE ROW(emp_row_type(cur.empno,cur.ename,cur.deptno)); END LOOP; RETURN; END; Carl Dudley – University of Wolverhampton 67 Table Function Joins SELECT * FROM dept, TABLE(get_all_emps(dept.deptno)); DEPTNO -----10 : 20 : 30 : DNAME -------------ACCOUNTING : RESEARCH : SALES : LOC ------------NEW YORK : DALLAS : CHICAGO : EMPNO -------7782 : 7369 : 7900 : SELECT * FROM dept, TABLE(get_all_emps(dept.deptno))(+); DEPTNO -----10 : 20 : 30 : 40 DNAME -------------ACCOUNTING : RESEARCH : SALES : OPERATIONS LOC ------------NEW YORK : DALLAS : CHICAGO : BOSTON EMPNO -------7782 : 7369 : 7900 : SELECT * FROM dept CROSS APPLY TABLE(get_all_emps(dept.deptno)); ENAME -------------------CLARK : SMITH : JAMES : DEPTNO -----10 : 20 : 30 : SELECT * FROM dept OUTER APPLY TABLE(get_all_emps(dept.deptno)); ENAME -------------------CLARK : SMITH : JAMES : Carl Dudley – University of Wolverhampton DEPTNO -----10 : 20 : 30 : 68 Oracle Join Techniques ANSI and Oracle Joins Two-way Outer Joins Join and Filter Conditions Chaining on the Outer Join Hash Join Trees Anti Joins and Semi Joins Lateral Joins Nested Loops Joins Join Elimination Carl Dudley – University of Wolverhampton 69 Oracle11g Nested Loops Joins SELECT /*+ LEADING(e) USE_NL(d)*/ * FROM emp e ,dept d WHERE e.deptno = d.deptno AND e.sal = 3000; Batch style operation using an index ― ROWIDs collected from an index ― Used in a second nested loops style operation against the driven table • Can reduce physical I/O and improve performance in certain cases -----------------------------------------| SELECT STATEMENT | | | NESTED LOOPS | | | NESTED LOOPS | | TABLE ACCESS FULL | EMP | | INDEX UNIQUE SCAN | PK_DEPT | | TABLE ACCESS BY INDEX ROWID| DEPT | ------------------------------------------ • Could reduce readability of execution plans Carl Dudley – University of Wolverhampton 70 Reverting to Oracle10g Nested Loops Joins Use a hint or set a parameter SELECT /*+ LEADING(e) USE_NL(d) NO_NLJ_BATCHING(d)*/ * FROM emp e ,dept d WHERE e.deptno = d.deptno AND e.sal = 3000; ALTER SESSION SET OPTIMIZER_FEATURES_ENABLE = '10.2.0.5'; -----------------------------------------| SELECT STATEMENT | | | NESTED LOOPS | | | TABLE ACCESS FULL | EMP | | TABLE ACCESS BY INDEX ROWID| DEPT | | INDEX UNIQUE SCAN | PK_DEPT | ------------------------------------------ Other relevant hints NLJ_BATCHING() NLJ_PREFETCH() NO_NLJ_PREFETCH() New undocumented parameter _nlj_batching_enabled (0 or 1) Carl Dudley – University of Wolverhampton 71 Oracle Join Techniques ANSI and Oracle Joins Two-way Outer Joins Join and Filter Conditions Chaining on the Outer Join Hash Join Trees Anti Joins and Semi Joins Lateral Joins Nested Loops Joins Join Elimination Carl Dudley – University of Wolverhampton 72 Join Elimination – the Ins and Outs Some unnecessary joins are eliminated SELECT e.ename ,e.deptno FROM emp e ,dept d WHERE e.deptno = d.deptno SELECT e.ename ,e.deptno FROM emp e ,dept d WHERE e.deptno = d.deptno(+) -----------------------------------------| Id | Operation | Name | Rows | -----------------------------------------| 0 | SELECT STATEMENT | | 14 | |* 1 | TABLE ACCESS FULL| EMP | 14 | -----------------------------------------Predicate Information (identified by operation id): --------------------------------------------------1 - filter("E"."DEPTNO" IS NOT NULL) No access to dept table (or any dept table index) in both cases on 11g Filter is unnecessary if deptno has a NOT NULL constraint Carl Dudley – University of Wolverhampton 73 Conditions for Join Elimination Oracle 10g Oracle11g Inner Join Outer join Inner Join Outer join No constraints Primary key on dept (or UK) Foreign key on deptno in emp Carl Dudley – University of Wolverhampton 74 Join Elimination - Antijoins Anti joins can also be eliminated SELECT e.empno, e.ename FROM emp e WHERE NOT EXISTS (SELECT 1 FROM dept d WHERE d.deptno = e.deptno); SELECT STATEMENT NESTED LOOPS ANTI TABLE ACCESS FULL EMP INDEX UNIQUE SCAN PK_DEPT No foreign key filter("E"."DEPTNO"="D”.”DEPTNO” SELECT STATEMENT TABLE ACCESS FULL EMP Foreign key present filter("E"."DEPTNO" IS NOT NULL) SELECT STATEMENT FILTER TABLE ACCESS FULL EMP filter(NULL IS NOT NULL) Foreign key and NOT NULL Dummy filter showing NO access to ANY table Carl Dudley – University of Wolverhampton 75 Join Elimination - Semijoins SELECT e.empno, e.ename FROM emp e WHERE EXISTS (SELECT 1 FROM dept d WHERE d.deptno = e.deptno); SELECT STATEMENT NESTED LOOPS SEMI TABLE ACCESS FULL EMP INDEX UNIQUE SCAN PK_DEPT No foreign key filter("E"."DEPTNO"="D”.”DEPTNO” SELECT STATEMENT TABLE ACCESS FULL EMP Foreign key present filter("E"."DEPTNO" IS NOT NULL) SELECT STATEMENT FILTER TABLE ACCESS FULL EMP Foreign key and NOT NULL No filter is necessary Carl Dudley – University of Wolverhampton 76 Outer Join Elimination - Implications A view used on the system ― Part of an application CREATE VIEW empdept AS SELECT e.ename ,e.job ,e.deptno ,d.dname ,d.loc FROM emp e ,dept d WHERE e.deptno = d.deptno(+); SELECT ename,job FROM empdept; ― No access made to dept table even though join is embedded in view • Access is only to the emp table • Does not eliminate access to emp when referencing columns in dept ― Control with hints ELIMINATE_JOIN NO_ELIMINATE_JOIN ― Control with hidden parameter _optimizer_join_elimination_enabled Carl Dudley – University of Wolverhampton 77 Undocumented Parameters KSPPINM --------------------------------------------_lm_node_join_opt _abort_recovery_on_join _hash_join_enabled _multi_join_key_table_lookup _force_hash_join_spill _always_anti_join _optimizer_null_aware_antijoin _convert_set_to_join _push_join_predicate _push_join_union_view _push_join_union_view2 _optimizer_join_sel_sanity_check _ordered_semijoin _always_semi_join _full_pwise_join_enabled _partial_pwise_join_enabled _index_join_enabled _improved_outerjoin_card _cost_equality_semi_join _new_initial_join_orders _oneside_colstat_for_equijoins _gs_anti_semi_join_allowed _optim_new_default_join_sel _optimizer_new_join_card_computation _optimizer_sortmerge_join_enabled _optimizer_dim_subq_join_sel _optimizer_join_order_control _optimizer_join_elimination_enabled _optimizer_sortmerge_join_inequality _selfjoin_mv_duplicates _optimizer_aw_join_push_enabled _optimizer_native_full_outer_join _optimizer_eliminate_filtering_join _optimizer_join_factorization _optimizer_outer_join_to_inner _optimizer_full_outer_join_to_outer _xsolapi_sql_all_multi_join_non_base_hints _xsolapi_sql_enable_aw_join KSPPSTVL --------FALSE FALSE TRUE TRUE FALSE CHOOSE TRUE FALSE TRUE TRUE TRUE TRUE TRUE CHOOSE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 3 TRUE TRUE TRUE TRUE FORCE TRUE TRUE TRUE TRUE SELECT ksppinm ,ksppstvl FROM x$ksppi I ,x$ksppcv v WHERE v.indx =i.indx AND ksppinm LIKE '%join%'; Around 2750 undocumented parameters on 11g TRUE Carl Dudley – University of Wolverhampton 78 Hints from v$sql_hint NAME ---------------------------APPEND NO_MONITORING NO_SQL_TUNE IGNORE_WHERE_CLAUSE NO_QUERY_TRANSFORMATION OPTIMIZER_FEATURES_ENABLE GATHER_PLAN_STATISTICS IGNORE_OPTIM_EMBEDDED_HINTS TABLE_STATS RULE CHOOSE FIRST_ROWS ORDERED ORDERED_PREDICATES PUSH_PRED ELIMINATE_JOIN NO_ELIMINATE_JOIN OUTER_JOIN_TO_INNER NO_OUTER_JOIN_TO_INNER HASH_AJ NL_AJ SEMIJOIN HASH_SJ NL_SJ STAR SET_TO_JOIN SQL_FEATURE ---------------------------QKSFM_CBO QKSFM_ALL QKSFM_ALL QKSFM_ALL QKSFM_TRANSFORMATION QKSFM_ALL QKSFM_GATHER_PLAN_STATISTICS QKSFM_ALL QKSFM_STATS QKSFM_RBO QKSFM_CHOOSE QKSFM_FIRST_ROWS QKSFM_CBO QKSFM_CBO QKSFM_FILTER_PUSH_PRED QKSFM_TABLE_ELIM QKSFM_TABLE_ELIM QKSFM_OUTER_JOIN_TO_INNER QKSFM_OUTER_JOIN_TO_INNER QKSFM_CBO QKSFM_CBO QKSFM_TRANSFORMATION QKSFM_CBO QKSFM_CBO QKSFM_STAR_TRANS QKSFM_SET_TO_JOIN CLASS -----------------------APPEND NO_MONITORING NO_SQL_TUNE IGNORE_WHERE_CLAUSE NO_QUERY_TRANSFORMATION OPTIMIZER_FEATURES_ENABL GATHER_PLAN_STATISTICS IGNORE_OPTIM_EMBEDDED_HI TABLE_STATS MODE MODE MODE ORDERED ORDERED_PREDICATES PUSH_PRED ELIMINATE_JOIN ELIMINATE_JOIN OUTER_JOIN_TO_INNER OUTER_JOIN_TO_INNER ANTIJOIN ANTIJOIN 273 hints on SEMIJOIN SEMIJOIN SEMIJOIN STAR SET_TO_JOIN Carl Dudley – University of Wolverhampton 79 11g Oracle Join Techniques Carl Dudley University of Wolverhampton, UK Oracle ACE Director carl.dudley@wlv.ac.uk Carl Dudley – University of Wolverhampton 80