2011-10-05 19 views
7

Ho una tabella con voci attive non attive, attivo = 1 per attivo e attivo = 0 per inattivo.Oracle: indicizzazione di un sottoinsieme di righe di una tabella

Ho una varietà di indici su questa tabella, ma ho bisogno solo degli indici mantenuti per le voci attive, poiché l'applicazione esegue solo query sui dati attivi. I dati inattivi devono essere conservati perché possono essere nuovamente attivi, ma in genere ciò avviene solo con aggiornamenti di massa, che comunque non utilizzano un indice.

Sto notando l'indicizzazione delle voci inattive (di cui ci sono sempre più di voci attive) richiede un po 'di spazio.

C'è un modo in Oracle (10g) per fare qualcosa di simile:

create index an_idx on tab (active, col1, col2, ... , coln) where active = 1?

tentativo precedente:

ho provato usando una funzione indice basato per impostare la prima colonna per nulla quando active = 0 modo:

create index an_idx on tab (decode(active, 1, 1, null), col1, col2, ... , coln)

Ma Oracle sembra ancora indicizzare le colonne inattive in questo caso.

risposta

7

Partiziona la tabella in base a ACTIVE, crea indici locali e crea gli indici per le partizioni inattive INUTILIZZABILI. Ciò eliminerà il tempo speso per l'indicizzazione dei dati inattivi.

create table tab(active number, col1 number, col2 number, col3 number) 
    partition by list(active) 
    (partition tab_active values(1), partition tab_inactive values(0)); 

create index tab_index1 on tab(col1) local; 

alter index tab_index1 modify partition tab_inactive unusable; 

Ma ci sono alcuni potenziali svantaggi di questo approccio:

  • Non tutti i tipi di indici possono essere inutilizzabili.
  • Non è normale avere oggetti inutilizzabili nel database. Probabilmente la gente si lamenterà o supporterà che sia un bug e ricostruirlo.
  • Alcune operazioni, quali il troncamento, renderanno automaticamente gli indici utilizzabili di nuovo.

In Oracle 12c è possibile eseguire questa utilizzando partial indexes:

create table tab(active number, col1 number, col2 number, col3 number) 
    partition by list(active) 
    (partition tab_active values(1) indexing on, 
    partition tab_inactive values(0) indexing off); 

create index tab_index1 on tab(col1) local indexing partial; 
1

Non credo sia possibile. Ci sono alcune opzioni

  1. fare un indice su (attiva, col1 ...) in modo che il tempo di query non è influenzato tanto da elementi inattivi
  2. Creare due tabelle per gli elementi attivi/inattivi e gestire stato attivo spostando le cose tra le due tabelle
  3. Creare una seconda tabella con tutti i dati che si desidera indicizzare, nonché un identificatore univoco e unirsi alla tabella per ottenere il resto dei dati.
+0

Se il risparmio di spazio è il vostro obiettivo, l'opzione 2 avrebbe senso IMO. –

11

L'idea di base è giusta, ma è necessario applicare la decodifica a tutte le colonne. Solo quando tutte le espressioni indicizzate sono NULL la riga non sarà indicizzata.

create index an_idx on tab (
    decode(active, 1, col1, null), 
    ... 
    decode(active, 1, coln, null) 
) 

Naturalmente, se poi si desidera una query per utilizzare questo indice, si deve usare le stesse espressioni nella clausola WHERE.

Nota Non credo che si voglia includere l'espressione decode(active, 1, 1, null) nell'indice, poiché sarebbe costante per tutte le righe indicizzate.

+0

Grazie per una soluzione. Ero preoccupato che avrei dovuto fare qualcosa di disordinato in questo modo. Pensavo ci potesse essere qualcosa di più pulito. – Clinton

Problemi correlati