Miałem okazję się tym pobawić, a moje poprzednie komentarze dotyczące NOT IN są w tym przypadku czerwone. Kluczową rzeczą jest obecność wartości NULL, a raczej to, czy indeksowane kolumny nie mają narzuconych ograniczeń NULL.
Będzie to zależeć od używanej wersji bazy danych, ponieważ optymalizator staje się coraz mądrzejszy z każdym wydaniem. Używam 11gR1 i optymalizator używał indeksu we wszystkich przypadkach z wyjątkiem jednego:gdy obie kolumny miały wartość null i nie uwzględniłem NOT IN
klauzula:
SQL> desc big_table
Name Null? Type
----------------------------------- ------ -------------------
ID NUMBER
COL1 NUMBER
COL2 VARCHAR2(30 CHAR)
COL3 DATE
COL4 NUMBER
Bez klauzuli NOT IN...
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>
Kiedy zdobyłem NOT IN
z powrotem, optymalizator zdecydował się na użycie indeksu. Dziwne.
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>
Powtórzę, we wszystkich innych przypadkach, o ile jedna z indeksowanych kolumn nie była pusta, indeks był używany do spełnienia zapytania. Może to nie być prawdą we wcześniejszych wersjach Oracle, ale prawdopodobnie wskazuje drogę naprzód.