2011-10-05 18 views
7

Tengo una tabla que tiene entradas activas inactivas, activo = 1 para activo y activo = 0 para inactivo.Oracle: indización de un subconjunto de filas de una tabla

Tengo una variedad de índices en esta tabla, pero solo necesito los índices mantenidos para entradas activas, ya que la aplicación solo consulta con datos activos. Los datos inactivos deben mantenerse porque pueden volver a activarse, pero esto generalmente solo se realiza con actualizaciones masivas, que de todos modos no usarían un índice.

Me doy cuenta de que indexar las entradas inactivas (hay cada vez más entradas activas) ocupa bastante espacio.

¿Hay alguna manera en Oracle (10g) para hacer algo como esto:

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

intento previo:

me trató de usar una función de índice basado para establecer la primera columna a la nula cuando active = 0 así:

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

Pero Oracle todavía parece índice de las columnas inactivos en este caso.

Respuesta

7

Particione la tabla por ACTIVE, cree índices locales y haga que los índices de las particiones inactivas no sean utilizables. Esto eliminará el tiempo dedicado a indexar datos inactivos.

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; 

Pero hay algunas desventajas potenciales a este enfoque:

  • No todos los tipos de índices puede ser inutilizable.
  • No es normal tener objetos inutilizables en la base de datos. La gente probablemente se quejará o asumirá que se trata de un error y lo reconstruirá.
  • Algunas operaciones, como truncar, volverán a utilizar automáticamente los índices.

En Oracle 12c se puede lograr esto usando 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

No creo que esto sea posible. Hay algunas opciones

  1. Hacer un índice en (activa, col1 ...) de manera que el tiempo de consulta no se ve afectada tanto por elementos inactivos
  2. Cree dos tablas para los elementos activos/inactivos y gestionar estado activo moviendo cosas entre las dos tablas
  3. Crea una segunda tabla con todos los datos que quieras indexar, así como un identificador único y únete a la tabla para obtener el resto de los datos.
+0

Si el ahorro de espacio es su objetivo, la opción 2 tendría sentido OMI. –

11

Su idea básica es correcta, pero debe aplicar la decodificación a todas las columnas. Solo cuando todas las expresiones indexadas sean NULL, la fila no se indexará.

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

Por supuesto, si a continuación, desea una consulta para utilizar este índice, se tiene que usar las mismas expresiones en la cláusula WHERE.

Nota: No creo que desee incluir la expresión decode(active, 1, 1, null) en el índice, ya que sería constante para todas las filas indexadas.

+0

Gracias por una solución. Estaba preocupado de tener que hacer algo desordenado como este. Pensé que podría haber algo más limpio. – Clinton

Cuestiones relacionadas