das sind natürlich zwei verschiedene Abfragen. Der Plan KANN sich ändern, wenn die Auswahlen unterschiedlich sind. d.h. in etw.* kann es sein, dass ein vollständiger/schneller vollständiger Index-Scan für die linke verbundene Tabelle ausgewählt wird. während es sich beim ersten möglicherweise um einen vollständigen Tabellenscan handelt.
Um Ihnen weiter zu helfen, können wir bitte die Pläne sehen? tun Sie dies vorzugsweise in 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;
BEARBEITEN
Angesichts Ihres Erklärungsplans sehen Sie bei jedem Schritt KARDINALITÄT =1? Sie haben Statistiken gesammelt, als die Tische leer waren! siehe hier:
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
siehe also, es hat 200314 IO verwendet und einige Sekunden gedauert. Siehe auch ROWS =1 bei jedem Schritt (d. h. die vollständigen Scans). Lasst uns Statistiken sammeln:
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.
und jetzt erneut ausführen: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: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>
Jetzt haben wir nur 2537 Gets verwendet und der Plan zeigt die richtigen ZEILEN und einen HASH-Join (besser für unsere Bedürfnisse). Meine Testtabellen sind wahrscheinlich kleiner als Ihre echten, weshalb die Timings näher liegen