Jeg har haft chancen for at lege med dette, og mine tidligere kommentarer vedrørende NOT IN er en rød sild i dette tilfælde. Det vigtigste er tilstedeværelsen af NULL'er, eller rettere sagt om de indekserede kolonner IKKE har håndhævet NULL-begrænsninger.
Dette kommer til at afhænge af den version af databasen, du bruger, fordi optimeringsværktøjet bliver smartere med hver udgivelse. Jeg bruger 11gR1, og optimeringsværktøjet brugte indekset i alle tilfælde undtagen ét:når begge kolonner var nul, og jeg ikke inkluderede NOT IN
klausul:
SQL> desc big_table
Name Null? Type
----------------------------------- ------ -------------------
ID NUMBER
COL1 NUMBER
COL2 VARCHAR2(30 CHAR)
COL3 DATE
COL4 NUMBER
Uden NOT IN-klausulen...
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>
Da jeg dobbede NOT IN
klausul tilbage i, valgte optimeringsværktøjet at bruge indekset. Underligt.
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>
Bare for at gentage, i alle andre tilfælde, så længe en af de indekserede kolonner blev erklæret ikke nul, blev indekset brugt til at tilfredsstille forespørgslen. Dette er muligvis ikke sandt på tidligere versioner af Oracle, men det peger sandsynligvis vejen frem.