En el sistema, toas las aplicaciones postean sus mensajes en una cola, y luego estos mensajes se graban en una serie de tablas, todas relacionadas con una tabla cabecera, que denominaremos log_sistema. Esta cabecera llega a recibir 36 millones de registros/día (si, son bastantes).
Diariamente se eliminan de esa tabla todos los registros anteriores a cierta fecha, a fin de mantener solamente una cantidad de días, para análisis de performance. Este proceso de borrado se hace automáticamente por medio de un SP que corre todos los días.
Para determinar el rango a borrar el SP realiza algunas consultas, buscando las fechas más antiguas, y es una de las comprobaciones la que nos está causando problemas.
En la consulta problemática, usamos dos variables, una NUMBER y otra DATE. La variable fechaHasta es una variable DATE que contiene un DateTime representando la fecha hasta la cual se borrarán registros.
Si usamos un rango:
Código SQL:
la consulta se ejecuta perfectamente y muy rápida.Ver original
SELECT COUNT(1) INTO totalDias FROM log_sistema WHERE TIEMPO BETWEEN fechaDesde AND fechaHasta AND ROWNUM = 1;
Pero si buscamos directamente la menor a esa fecha:
Código SQL:
la consulta dura una enormidad y termina cayendo por "snapshot too old". Ver original
SELECT COUNT(1) INTO totalDias FROM log_sistema WHERE TIEMPO < fechaHasta AND ROWNUM = 1;
Un detalle: No podemos modificar los segmentos de rollback porque los administradores de base de datos no lo autorizan, así que esa solución no es una opción.
El misterio: Lo que no podemos entender es por qué falla, teniendo en cuenta que estamos usando un INDEX sobre el campo "TIEMPO", y pidiendo que busque el menor a cierta fecha, ambas cosas contenidas en el indice.
¿Qué puede causar que falle esta consulta tan elemental, cuyo plan de consulta usa efectivamente (ya lo comprobamos) el indice definido para el campo?