Man kann die merkwürdige NULL
-Indizierung ausnutzen, um partielle Indizes in der Oracle Datenbank umzusetzen. Dafür verwendet man einfach NULL
für Zeilen, die nicht indiziert werden sollen.
Als Beispiel werden wir den folgenden partiellen Index in der Oracle Datenbank umsetzen:
CREATE INDEX messages_todo
ON messages (receiver)
WHERE processed = 'N'
Dafür benötigen wir zuerst eine Funktion, die den RECEIVER
-Wert nur liefert, wenn der PROCESSED
-Wert 'N'
ist.
CREATE OR REPLACE
FUNCTION pi_processed(processed CHAR, receiver NUMBER)
RETURN NUMBER
DETERMINISTIC
AS BEGIN
IF processed IN ('N') THEN
RETURN receiver;
ELSE
RETURN NULL;
END IF;
END
Die Funktion muss natürlich deterministisch sein, damit sie in einer Indexdefinition verwendet werden kann.
Hinweis in eigener Sache
Ich lebe von SQL-Schulungen, SQL-Tuning und Beratung sowie dem Verkauf meines Buches „SQL Performance Explained“. Mehr auf winand.at.
Damit kann man einen Index anlegen, der nur Zeilen mit dem PROCESSED
-Wert 'N'
beinhaltet:
CREATE INDEX messages_todo
ON messages (pi_processed(processed, receiver))
Damit der Index benutzt wird, muss man in der Abfrage den indizierten Ausdruck verwenden:
SELECT message
FROM messages
WHERE pi_processed(processed, receiver) = ?
----------------------------------------------------------
|Id | Operation | Name | Cost |
----------------------------------------------------------
| 0 | SELECT STATEMENT | | 5330 |
| 1 | TABLE ACCESS BY INDEX ROWID| MESSAGES | 5330 |
|*2 | INDEX RANGE SCAN | MESSAGES_TODO | 5303 |
----------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("PI_PROCESSED"("PROCESSED","RECEIVER")=:X)