OracleがインデックスにおいてNULL
を扱うこの奇妙な
方法を利用すると、部分インデックスをエミュレートできます。インデックスに含みたくない行でNULL
をうまく使う必要が
あります。
以下の部分インデックスをエミュレートしてみましょう。
CREATE INDEX messages_todo
ON messages (receiver)
WHERE processed = 'N'
まず、PROCESSED
が'N'
の時だけ
RECEIVER
を返す関数が必要です。
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
この関数は、インデックスの定義に 使えるよう、確定的である必要があります。
協力してください
この記事が気に入ったら、私の書いた本「SQLパフォーマンス詳解」や私によるトレーニングもきっと気にいるはず。
これで、PROCESSED='N'
の行だけを含むインデックスを作ることができました。
CREATE INDEX messages_todo
ON messages (pi_processed(processed, receiver))
このインデックスを使うには、クエリ内ではインデックスを使った表現をする必要があります。
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)