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)
