Ik heb de kans gehad om hiermee te spelen, en mijn eerdere opmerkingen over de NOT IN zijn in dit geval een rode haring. Het belangrijkste is de aanwezigheid van NULL's, of beter gezegd of de geïndexeerde kolommen GEEN NULL-beperkingen hebben.
Dit zal afhangen van de versie van de database die je gebruikt, omdat de optimizer met elke release slimmer wordt. Ik gebruik 11gR1 en de optimizer gebruikte de index in alle gevallen behalve één:wanneer beide kolommen nul waren en ik de NOT IN
niet had opgenomen clausule:
SQL> desc big_table
Name Null? Type
----------------------------------- ------ -------------------
ID NUMBER
COL1 NUMBER
COL2 VARCHAR2(30 CHAR)
COL3 DATE
COL4 NUMBER
Zonder de NOT IN-clausule...
SQL> explain plan for
2 select col4, count(col1) from big_table
3 group by col4
4 /
Explained.
SQL> select * from table(dbms_xplan.display)
2 /
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------
Plan hash value: 1753714399
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 31964 | 280K| | 7574 (2)| 00:01:31 |
| 1 | HASH GROUP BY | | 31964 | 280K| 45M| 7574 (2)| 00:01:31 |
| 2 | TABLE ACCESS FULL| BIG_TABLE | 2340K| 20M| | 4284 (1)| 00:00:52 |
----------------------------------------------------------------------------------------
9 rows selected.
SQL>
Toen ik de NOT IN
. deed clausule terug in, heeft de optimizer ervoor gekozen om de index te gebruiken. Raar.
SQL> explain plan for
2 select col4, count(col1) from big_table
3 where col1 not in (12, 19)
4 group by col4
5 /
Explained.
SQL> select * from table(dbms_xplan.display)
2 /
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------
Plan hash value: 343952376
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 31964 | 280K| | 5057 (3)| 00:01:01 |
| 1 | HASH GROUP BY | | 31964 | 280K| 45M| 5057 (3)| 00:01:01 |
|* 2 | INDEX FAST FULL SCAN| BIG_I2 | 2340K| 20M| | 1767 (2)| 00:00:22 |
----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------
2 - filter("COL1"<>12 AND "COL1"<>19)
14 rows selected.
SQL>
Gewoon om te herhalen, in alle andere gevallen, zolang een van de geïndexeerde kolommen niet nul werd verklaard, werd de index gebruikt om aan de zoekopdracht te voldoen. Dit is misschien niet het geval in eerdere versies van Oracle, maar het wijst waarschijnlijk de weg vooruit.