Ich hatte die Gelegenheit, damit herumzuspielen, und meine vorherigen Kommentare bezüglich NOT IN sind in diesem Fall ein Ablenkungsmanöver. Das Wichtigste ist das Vorhandensein von NULL-Werten, oder besser gesagt, ob für die indizierten Spalten NOT-NULL-Einschränkungen erzwungen werden.
Dies hängt von der Version der Datenbank ab, die Sie verwenden, da der Optimierer mit jeder Version intelligenter wird. Ich verwende 11gR1 und der Optimierer hat den Index in allen Fällen verwendet, außer in einem:als beide Spalten null waren und ich NOT IN
nicht eingeschlossen habe Klausel:
SQL> desc big_table
Name Null? Type
----------------------------------- ------ -------------------
ID NUMBER
COL1 NUMBER
COL2 VARCHAR2(30 CHAR)
COL3 DATE
COL4 NUMBER
Ohne die NOT IN-Klausel...
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>
Als ich den NOT IN
getippt habe -Klausel wieder eingefügt, hat sich der Optimierer für die Verwendung des Index entschieden. Seltsam.
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>
Um es noch einmal zu wiederholen:In allen anderen Fällen wurde der Index verwendet, um die Abfrage zu erfüllen, solange eine der indizierten Spalten als nicht null deklariert wurde. Dies trifft möglicherweise nicht auf frühere Versionen von Oracle zu, weist aber wahrscheinlich den Weg nach vorn.