Per prima cosa assicurati di aver compreso correttamente la domanda:
- Vuoi accelerare
SELECT .. WHERE C_D IS NULL
ma tu non desidera velocizzare le query che cercano un C_D non NULL. - Vuoi anche assicurarti che nell'indice non siano presenti valori non NULL "non necessari", per risparmiare spazio.
Se tale comprensione è corretta, ciò di cui hai bisogno è un funzionale indice. Cioè. un indice su una funzione su un campo, non un campo stesso...
CREATE INDEX T_IE1 ON T (CASE WHEN C_D IS NULL THEN 1 ELSE NULL END) COMPRESS
...che quindi interrogheresti come...
SELECT * FROM T WHERE (CASE WHEN C_D IS NULL THEN 1 ELSE NULL END) = 1
...che equivale a...
SELECT * FROM T WHERE C_D IS NULL
...ma più veloce poiché usa l'indice:
Ciò consente di risparmiare spazio perché gli indici a colonna singola non memorizzano NULL. Inoltre, usa COMPRESS
poiché l'indice conterrà sempre solo una chiave, quindi non è necessario sprecare spazio nel ripetere la stessa chiave più e più volte nella struttura dell'indice.
NOTA:in Oracle 11, puoi anche creare una colonna virtuale basata su funzioni (basato sul CASE
espressione sopra), quindi indicizza ed esegui query direttamente su quella colonna, per salvare una digitazione ripetitiva.
--- MODIFICA ---
Se sei interessato anche a interrogare su C_I insieme a C_D IS NULL
, potresti...
CREATE UNIQUE INDEX T_IE2 ON T (C_I, CASE WHEN C_D IS NULL THEN 1 ELSE NULL END)
...e interrogalo con (ad esempio)...
SELECT * FROM T WHERE C_I > 'some value' AND (CASE WHEN C_D IS NULL THEN 1 ELSE NULL END) = 1
...che equivale a...
SELECT * FROM T WHERE C_I > 'some value' AND C_D IS NULL
...ma più veloce, poiché usa l'indice T_IE2
.
Questo è infatti l'unico indice di cui hai bisogno sulla tua tabella (copre la chiave primaria, quindi non hai più bisogno di un indice separato solo su C_I). Ciò significa anche che uno stesso ROWID non viene mai archiviato in più di un indice, risparmiando spazio.
NOTA:COMPRESS
non ha più senso per l'indice T_IE2
.
--- MODIFICA 2 ---
Se ti interessa la semplicità più dello spazio, puoi semplicemente creare un indice composito su {C_I, C_D}. Oracle memorizza i valori NULL nell'indice composito purché nella stessa tupla sia presente almeno un valore non NULL:
CREATE UNIQUE INDEX T_IE3 ON T (C_I, C_D)
Questo utilizza l'indice:
SELECT * FROM T WHERE C_I > 1 AND C_D IS NULL
Come nella precedente EDIT, questo è l'unico indice di cui hai bisogno sulla tua tabella.