el orden de oráculo corre terriblemente lento

Estoy haciendo una consulta como esta y me toma 6 segundos completarla:

select * 
from ( select aaa."ID" 
      from "aaa"  
      where aaa."DELETED" is null 
      order by aaa."CREATED" desc ) 
where rownum <= 15;

Tengo alrededor de 1.6 millones de registros en mi tabla e intenté agregar un índice separado a la columna eliminada y a la columna creada, intenté agregar un índice que contenía columnas creadas y eliminadas e intenté crear el mismo índice en diferente orden. Nada parece ayudar. ¿Qué puedo hacer para acelerar esto?

No puedo cambiar mucho la consulta porque es generada por hibernación

Editar: incluso sin aaa."DELETED" is null la consulta se está ejecutando muy lentamente.

Editar 2: Plan de consulta

Edición 3: agregando mi definición de índice. Sinceramente, no sé qué significan la mayoría de estos números, estoy usando sqldeveloper para crear índices. Ni siquiera sabía que hay tantas opciones de configuración para cada índice, ahora buscaré en la documentación.

CREATE INDEX "aaa"."aaa_CREATED_ASC" ON "aaa"."aaa"
  (
    "CREATED"
  )
  PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE
  (
    INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT
  )
  TABLESPACE "SYSTEM" ;
CREATE INDEX "aaa"."aaa_CREATED_DESC" ON "aaa"."aaa"
  (
    "CREATED" DESC
  )
  PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE
  (
    INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT
  )
  TABLESPACE "SYSTEM" ;

preguntado el 08 de noviembre de 11 a las 13:11

¿Qué aspecto tiene el plan de consultas? -

¿La imagen que agregué al plan de consulta? :) (soy nuevo en la terminología de Oracle, soy un chico de mysql: D) -

Así que está tomando una tabla con millones de filas, ordenándolas y luego mirando las primeras 15, que es todo lo que le interesa. Debería mirar las funciones analíticas de Oracle. Ver, por ejemplo, stackoverflow.com/questions/5636507/… -

Ese plan de explicación parece ser para una tabla sin índices. O al menos, para una tabla sin índice en CREATED. Además, ¿qué versión de la base de datos está utilizando? El optimizador de Oracle mejora con cada lanzamiento. -

Definitivamente hay índices en la columna creada (actualicé la pregunta con su código). uno ASC el otro DESC. pero estoy de acuerdo, no se están utilizando. Intenté proporcionar una sugerencia de índice en la consulta, pero no funcionó. -

2 Respuestas

Debe comprender cómo Oracle accede a los registros de la base de datos. Una lectura de índice es una acción, una lectura de tabla es otra acción. Entonces, para recuperar un registro indexado de una tabla es un mínimo de dos lecturas.

Su consulta utiliza tres piezas de información:

  • la columna ELIMINADA (criterio de restricción)
  • la columna CREADO (criterio de clasificación)
  • el ID (conjunto de resultados)

Oracle no indexa valores NULL, por lo que un índice de una sola columna en DELETED no te ayudará. Eso es un escaneo de tabla completo, y no es mejor que ningún índice.

Un índice sobre CREATED por sí solo es mejor porque la ruta de acceso se convertirá en:

INDEX FULL SCAN DESCENDING

Es decir, comienza con las fechas más recientes del índice y funciona al revés. Sin embargo, la consulta aún necesitará leer la tabla para encontrar el ID y los valores ELIMINADOS. Pueden ser muchas lecturas de tabla, dependiendo de la frecuencia con la que ELIMINADO sea nulo.

Ahora, un índice compuesto en (CREATED, DELETED) en ese orden debería ser más útil, porque Oracle ahora indexará los NULL en el DELETED columna. Oracle puede usar el índice para asegurarse de que solo busque registros de tablas para obtener el ID valores. Serán quince lecturas de mesa.

Finalmente, podría construir un índice compuesto en (CREATED, DELETED, ID) y dar servicio a toda la consulta desde el índice. Esa es la opción más rápida hasta ahora.

Luego, solo tiene que decidir si los beneficios de rendimiento justifican la sobrecarga de mantener el índice. Por lo que vale, el costo de mantener un índice compuesto agrega una pequeña fracción al costo de mantener un índice de una sola columna.


Por cierto, consultas horribles como esta son una de las razones por las que es una mala idea utilizar la eliminación lógica. Elimine físicamente sus registros y utilice tablas de diario para recuperar el estado histórico de su tabla cuando lo necesite.

respondido 08 nov., 11:18

+1, aunque el índice (created,deleted) solo se usará si CREATED no es anulable (poco probable de la pregunta OP) o si la consulta se modifica para incluir el predicado where created is not null. - Vincent Malgrat

muchas gracias. Basado en su respuesta, pensé que el truco era agregar la columna de identificación al índice. entonces es ahora (creado, id). No agregué la columna eliminada allí porque quiero que se use también para otras consultas y el beneficio de rendimiento de tener la columna eliminada fue insignificante. - Yervand Aghababyan

@VincentMalgrat - punto justo. Me temo que asumí que todos los registros se habrían llenado CREADO (de lo contrario, ¿cuál es el punto de tal columna?). - APC

intenta mirar aquí

http://www.dba-oracle.com/oracle_tips_null_idx.htm.

Además (aunque dudo que ayude aquí), hay consultas nativas en hibernación en caso de que las consultas generadas sean demasiado lentas.

respondido 08 nov., 11:17

si elimino completamente el deleted is null parte de la consulta que todavía se está ejecutando a los 5.9 segundos. así que no creo que esto ayude :( - Yervand Aghababyan

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.