DBAtlas · Atlas de operaciones de bases de datos

Plan de consulta degradado (lentitud repentina)

Una consulta que ayer era rápida hoy es de repente lenta. Normalmente el optimizador ha cambiado a un plan peor. Buscamos la causa raíz entre estadísticas desactualizadas, sensibilidad a parámetros, crecimiento del volumen de datos o un cambio repentino de plan, y estabilizamos el plan.

¿El plan cambió realmente, y cuándo?

¿Hay varios planes (plan_hash/plan_generation) para la misma consulta, y cuándo empezó la lentitud? ¿Coincide con un despliegue reciente, una actualización, un cambio de parámetros o una carga de datos grande?

SELECT sql_id, plan_hash_value, executions, ROUND(elapsed_time/GREATEST(executions,1)/1e6,3) AS sec_per_exec, first_load_time
FROM v$sql WHERE sql_id='&sqlid' ORDER BY first_load_time;
  • Las estadísticas pueden estar desactualizadas
  • La misma consulta se comporta de forma distinta según el parámetro (sniffing/peeking)
  • El volumen de datos ha crecido considerablemente
  • El plan cambió de repente tras una actualización/flush

¿Están actualizadas las estadísticas?

El optimizador basa sus decisiones en las estadísticas. Si la fecha del último analyze es antigua o el contador de modificaciones es alto, las estimaciones pueden haberse desviado realmente, lo que lleva a un plan malo.

SELECT table_name, num_rows, last_analyzed, stale_stats
FROM dba_tab_statistics WHERE table_name='T';
  • Las estadísticas están desactualizadas/faltan
  • Las estadísticas están actualizadas, pero el plan sigue siendo sensible a parámetros

¿Hay sensibilidad a parámetros?

La consulta elige y almacena en caché un plan según el valor del parámetro de su primera ejecución (MSSQL parameter sniffing / Oracle bind peeking). Ese plan puede ser malo para otros valores con una distribución sesgada.

SELECT sql_id, child_number, plan_hash_value, is_bind_sensitive, is_bind_aware
FROM v$sql WHERE sql_id='&sqlid';
  • Sí, el plan alterna entre bueno y malo según el parámetro
  • Se conoce el plan correcto; quiero fijarlo de forma permanente

Causa raíz: estadísticas desactualizadas / ausentes

Basándose en estadísticas antiguas que no se corresponden con la realidad, el optimizador estimó mal el número de filas y eligió un plan malo. Es la causa más común de degradación de planes.

Causa raíz: sensibilidad a parámetros (sniffing / bind peeking)

El plan en caché se eligió para el primer valor de parámetro que llegó y es malo para otros valores con una distribución sesgada. El objetivo es asegurarse de que se elige un plan adecuado al valor.

Solución: fijar el plan correcto (baseline / force plan)

Si existe un plan bueno conocido, fijarlo para que el optimizador no se desvíe de él detiene la degradación de forma permanente.

Causa raíz: el volumen de datos creció y el plan ya no es adecuado

A medida que crece la tabla, un plan que antes era ideal (p. ej. nested loop) ahora escala mal; el optimizador necesita estadísticas y rutas de acceso que reflejen correctamente el crecimiento.

Causa raíz: cambio repentino de plan (actualización / vaciado de caché)

El plan cambió de repente tras una actualización de versión, un cambio de parámetros o el vaciado de la caché de planes. El comportamiento del optimizador o las condiciones del entorno han cambiado.

Abrir en DBAtlas →