Pregunta

Tengo una tabla con particiones de esta manera:

create table demo (
    ID NUMBER(22) not null,
    TS TIMESTAMP not null,
    KEY VARCHAR2(5) not null,
    ...lots more columns...
)

La partición está en la columna de la TS (una partición por año).

Desde que busco una gran cantidad a través de la marca de tiempo, que crea un índice combinado:

create index demo.x1 on demo (ts, key);

Las miradas consulta como la siguiente:

select *
from demo t
where t.TS = to_timestamp('2009-06-30 07:47:57', 'YYYY-MM-DD HH24:MI:SS')

También intentó añadir and t.KEY = '00101' pero eso no ayuda.

Pero EXPLAIN PLAN dice que TABLE ACCESS y FULL:

#  Operation         Options Object Mode           Cost    Bytes   Cardinality
0  SELECT STATEMENT                ALL_ROWS        583804  287145  2127
1  PARTITION RANGE   ALL                           583804  287145  2127
2  TABLE ACCESS      FULL  HEADER  ANALYZED        583804  287145  2127

No se hace mención del índice. ¿Qué podría estar mal?

[EDIT] Por alguna razón, Oracle calculó mal por completo el costo de la operación. Tengo 112 millones de filas de esa tabla. El costo de un análisis completo de una sola partición debe ser de 20 millones de dólares, no 600.000. Es por eso que incluso ignora optimizador consejos.

[Edit2] Durante mis pruebas, pasó por encima de este resultado desconcertante. Cuando ejecuto este select:

select tx_ts
from kt.header
where tx_ts = to_timestamp('2009-06-30 07:47:57', 'YYYY-MM-DD HH24:MI:SS')

Me sale este Explain Plan:

0  SELECT STATEMENT                             ALL_ROWS  152  15616  1952
1  PARTITION RANGE    ALL                                 152  15616  1952
2  INDEX              FAST FULL SCAN  HEADERX2  ANALYZED  152  15616  1952

Así que cuando me limito a la columna indexada como el resultado de la select, Oracle decide utilizar el índice. Cuando quiero obtener todas las columnas, tengo que esperar a que un escaneo completo de tabla. ¿Qué está pasando aquí?

[Edit2] encontrado que es; ver mi respuesta a continuación.

¿Fue útil?

Solución

Está bien, fue un error de mi parte: La columna tenía el DATE tipo, no TIMESTAMP. Desde que utiliza to_timestamp(), Oracle no veía manera de utilizar el índice.

Otros consejos

En realidad no soy un experto en la partición, pero creo que lo que ha sucedido es que se ha creado un índice global - un único índice que las cubiertas filas en todas las particiones. Por lo tanto, el optimizador tiene que elegir entre dos caminos mutuamente excluyentes de acceso: (a) un escaneo intervalo de índice, o (B) de poda partición. Creo que la operación PARTICIÓN GAMA indica que ha elegido B.

Actualización de estadísticas, como han sugerido otros, pueden cambiar el comportamiento. Cuando se le cae y vuelve a crear el índice, de desechar cualquier estadística que existían para el índice.

Crear el índice como único, si la marca de tiempo y la clave se identifican de forma única una fila, sería una idea buena y podría cambiar el comportamiento.

Sin embargo, creo que la verdadera "solución" es que en su lugar debe crear índices locales - un índice separado en cada partición. Esto debería permitir que el optimizador de hacer la poda partición seguida de una búsqueda de índice. Honestamente, no estoy seguro de lo que es la sintaxis exacta para hacer esto. Tal vez lo que crea el índice en cada partición usando explícitamente los nombres de partición individual.

Si todo lo demás falla, puede intentar una sugerencia de optimizador:

select /*+ index(demo.demo demo.x1) */ *
from demo t
where t.TS = to_timestamp('2009-06-30 07:47:57', 'YYYY-MM-DD HH24:MI:SS')

Son sus estadísticas hasta la fecha? las estadísticas no válidos puede significar que Oracle cree un escaneo completo de tabla es más rápido que usar el índice. ¿Está utilizando cualquier insinuación en su consulta que podría estar diciendo oráculo para hacer una exploración completa?

¿Nos puede suministrar con la consulta completa y explicar los resultados del plan?

Editar: Aaron, puede actualizar las estadísticas de uso de "dbms_stats.gather_schema_stats" o "comandos dbms_stats.gather_table_stats". Ver aquí para obtener más información sobre los comandos. Esto actualizará todas las estadísticas relevantes para el esquema o tabla especificada. Costo de Oracle basado Optimizador utilizará las estadísticas para determinar qué plan de ejecución para elegir. Nunca utiliza los tamaños reales de la tabla. Tendrá que volver a actualizar sus estadísticas cuando el tamaño de la tabla cambia significativamente (+/- 10% o menos)

Otra cosa. Cuando se utiliza un índice compuesto, es necesario especificar todas las columnas utilizadas en el índice de la consulta para el optimizador de considerar el índice (y creo que es necesario especificar en el mismo orden, así, aunque podría ser de mal eso, se ha pasado un tiempo desde que miraba estas cosas)

No sólo puede ser un error tipográfico en su transcripción de la sentencia "CREATE INDEX ..." que usted envió, pero ¿está seguro de que realmente han creado el índice?

Para darnos una idea de primer paso de las estadísticas se puede usar estas consultas:

select table_name, num_rows
  from user_tables
  where table_name = 'DEMO';

 select table_name, num_rows
   from user_tab_partitions
   where table_name = 'DEMO';

 select index_name, num_rows from user_indexes                    
  where table_name in                   
    (select table_name                                   
      from user_tables where table_name = 'DEMO');

Además, exactamente cómo estás generando el PLAN explique? ¿Tiene acceso al host de base de datos para recuperar un archivo de rastreo si se habilita el rastreo?

[editar] Como os comentaba, sería bueno ver la traza de una ejecución real de la consulta. Puesto que usted ha indicado que tiene acceso a los sistemas de archivos de host db, ejecutar una secuencia de comandos SQL que (en la misma sesión) emite la siguiente:

alter session set sql_trace=true;
select /* THIS IS THE TRACE */  
*
from demo t
where t.TS = to_timestamp('2009-06-30 07:47:57', 'YYYY-MM-DD HH24:MI:SS');
exit
  • Después de las salidas de guión, averiguar donde el directorio de archivo de traza es por esta consulta:

    Seleccione el valor del parámetro v $ donde nombre = 'user_dump_dest';

  • herramienta de búsqueda Utilice lo que es a su disposición para encontrar el archivo que incluye la cadena "ESTE ES EL TRACE "

  • Proceso / profile del archivo de rastreo por emitir el comando del sistema operativo TKPROF traceFileName.trc tkprof.out

Examine este archivo - verá alguna información de cabecera, pero no habrá una sección que detalla la real plan de ejecución y estadísticas para la consulta. Si ves los mismos resultados en esta información, el siguiente paso es añadir otra declaración (después de la primera "sesión alter") que va a volcar información sobre por qué el Oracle CBO está ignorando el índice:

ALTER SESSION SET EVENTS='10053 trace name context forever, level 1';
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top