Oracle
 sql >> Database >  >> RDS >> Oracle

Oracle 11 Index solo per una parte dei dati

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.