są to oczywiście dwa różne zapytania. plan MOŻE się zmienić, a wybrane są inne. np. w sth.* może wybierać pełne/szybkie pełne skanowanie indeksu na lewej połączonej tabeli. podczas gdy na pierwszym będzie to prawdopodobnie pełne skanowanie tabeli.
aby jeszcze bardziej Ci pomóc, czy możemy zobaczyć plany? najlepiej zrobić to w SQL*PLUS
set timing on
set autotrace on traceonly
select s.* from sales_unit s left join sales_unit_relation r on (s.sales_unit_id = r.sales_unit_child_id) where r.sales_unit_child_id is null;
select * from sales_unit s left join sales_unit_relation r on (s.sales_unit_id = r.sales_unit_child_id) where r.sales_unit_child_id is null;
EDYTUJ
biorąc pod uwagę twój plan wyjaśnień, widzisz KARDYNAŁOŚĆ=1 na każdym kroku? zebrałeś statystyki, gdy stoły były puste! zobacz to:
SQL> select s.* from sales_unit s left join sales_unit_relation r on (s.sales_unit_id = r.child_sales_unit_id) where r.child_sales_unit_id is null;
no rows selected
Elapsed: 00:00:03.19
Execution Plan
----------------------------------------------------------
Plan hash value: 1064670292
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 48 | 27 (86)| 00:00:01 |
| 1 | NESTED LOOPS ANTI | | 1 | 48 | 27 (86)| 00:00:01 |
| 2 | TABLE ACCESS FULL| SALES_UNIT | 1 | 35 | 2 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | SALES_REL_IX1 | 1 | 13 | 25 (92)| 00:00:01 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("S"."SALES_UNIT_ID"="R"."CHILD_SALES_UNIT_ID")
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
200314 consistent gets
2220 physical reads
0 redo size
297 bytes sent via SQL*Net to client
339 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
więc zobacz, że użył 200314 IO i zajęło kilka sekund. Zobacz także ROWS =1 na każdym kroku (tj. pełne skany).. zbierz statystyki:
SQL> begin dbms_stats.gather_table_stats(user, 'SALES_UNIT', degree=>8, cascade=>true); end;
2 /
PL/SQL procedure successfully completed.
SQL> begin dbms_stats.gather_table_stats(user, 'SALES_UNIT_RELATION', degree=>8, cascade=>true); end;
2 /
PL/SQL procedure successfully completed.
a teraz rerun:SQL> wybierz s.* z sales_unit s left dołącz do sales_unit_relation r on (s.sales_unit_id =r.child_sales_unit_id) gdzie r.child_sales_unit_id ma wartość null;
no rows selected
Elapsed: 00:00:00.84
Execution Plan
----------------------------------------------------------
Plan hash value: 2005864719
-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 912 | 18240 | | 1659 (3)| 00:00:20 |
|* 1 | HASH JOIN ANTI | | 912 | 18240 | 2656K| 1659 (3)| 00:00:20 |
| 2 | TABLE ACCESS FULL | SALES_UNIT | 100K| 1472K| | 88 (3)| 00:00:02 |
| 3 | INDEX FAST FULL SCAN| SALES_REL_IX1 | 991K| 4841K| | 618 (3)| 00:00:08 |
-----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("S"."SALES_UNIT_ID"="R"."CHILD_SALES_UNIT_ID")
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
2537 consistent gets
0 physical reads
0 redo size
297 bytes sent via SQL*Net to client
339 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
SQL>
teraz użyliśmy tylko 2537 pobiera, a plan pokazuje właściwe ROWS i złącze HASH (lepiej dla naszych potrzeb). moje tabele testowe są prawdopodobnie mniejsze niż twoje prawdziwe, dlatego czasy są bliższe