When we create a join between 2 tables in Oracle, with some additional filter condition on one or both tables, will oracle join the tables first and then filter or will it filter the conditions first and then join.
Or in simple words, which of these 2 is a better query
Say we have 2 tables Employee and Department, and I want employees all employee + dept det开发者_C百科ail where employee salary is grater than 50000
Query 1: select e.name, d.name from employee e, department d where e.dept_id=d.id and e.salary>50000;
Query 2: select e.name, d.name from (select * from employee where salary>50000) e, department d where e.dept_id=d.id;
Generally it will filter as much as possible first. From the explain plan, you can actually see where the filtering is done, and where the joining is done, for example, create some tables and data:
create table employees (id integer, dept_id integer, salary number);
create table dept (id integer, dept_name varchar2(10));
insert into dept values (1, 'IT');
insert into dept values (2, 'HR');
insert into employees
select level, mod(level, 2) + 1, level * 1000
from dual connect by level <= 100;
create index employee_uk1 on employees (id);
create index dept_uk1 on dept (id);
exec dbms_stats.gather_table_stats(user, 'DEPT');
Now if I explain both the queries you provided, you will find that Oracle transforms each query into the same plan behind the scenes (it doesn't always execute what you think it does - Oracle has license to 'rewrite' the query, and it does it a lot):
explain plan for
select e.*, d.*
from employees e, dept d
where e.dept_id = d.id
and e.salary > 5000;
select * from table(dbms_xplan.display());
------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 96 | 1536 | 6 (17)| 00:00:01 |
| 1 | MERGE JOIN | | 96 | 1536 | 6 (17)| 00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID| DEPT | 2 | 12 | 2 (0)| 00:00:01 |
| 3 | INDEX FULL SCAN | DEPT_UK1 | 2 | | 1 (0)| 00:00:01 |
|* 4 | SORT JOIN | | 96 | 960 | 4 (25)| 00:00:01 |
|* 5 | TABLE ACCESS FULL | EMPLOYEES | 96 | 960 | 3 (0)| 00:00:01 |
4 - access("E"."DEPT_ID"="D"."ID")
filter("E"."DEPT_ID"="D"."ID")
5 - filter("E"."SALARY">5000)
Notice the filter operations applied to the query. Now explain the alternative query:
explain plan for
select e.*, d.*
from (select * from employees where salary > 5000) e, dept d
where e.dept_id = d.id;
------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 96 | 1536 | 6 (17)| 00:00:01 |
| 1 | MERGE JOIN | | 96 | 1536 | 6 (17)| 00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID| DEPT | 2 | 12 | 2 (0)| 00:00:01 |
| 3 | INDEX FULL SCAN | DEPT_UK1 | 2 | | 1 (0)| 00:00:01 |
|* 4 | SORT JOIN | | 96 | 960 | 4 (25)| 00:00:01 |
|* 5 | TABLE ACCESS FULL | EMPLOYEES | 96 | 960 | 3 (0)| 00:00:01 |
4 - access("EMPLOYEES"."DEPT_ID"="D"."ID")
filter("EMPLOYEES"."DEPT_ID"="D"."ID")
5 - filter("SALARY">5000)
Once you learn how to get the explain plans and how to read them, you can generally work out what Oracle is doing as it executes your query.
精彩评论