Saltar al contenido
WaitScope Entrar Solicitar acceso (por correo) Menú

Muchos hard parses

El hallazgo HARD_PARSE aparece cuando buena parte de los PARSE de la sesión son hard parse, o cuando el PARSE de SQL con literales pesa en el tiempo. La causa más común es SQL sin bind variables.

Se aplica a: Traces 10046, con o sin esperas

El hard parse es el parse completo de un SQL que la base de datos no encontró listo en la shared pool. Hecho en masa, gasta CPU y disputa estructuras con las otras sesiones; la causa más común es SQL con los valores en el texto, sin bind variables.

Síntomas

En el Diagnóstico aparece el hallazgo Muchos hard parses (HARD_PARSE). El texto dice cuántos PARSE fueron hard parse, por ejemplo 1.800 de 2.000 PARSE fueron hard parse, y, cuando hay sentencias que solo difieren en literales, agrega Hay 12 grupos de sentencias que solo difieren en literales: use variables bind.

El hallazgo aparece en dos casos. En el primero, la sesión hace muchos PARSE y buena parte de ellos son hard parse (columna Misses de la fila PARSE en Tipos de llamada). En el segundo, los hard parse vienen de muchas variantes de SQL con solo los literales diferentes y su PARSE pesa en el tiempo total, aunque el resto de la sesión haga soft parse. El porcentaje junto al título es el tiempo de los PARSE sobre el tiempo total: de todos ellos en el primer caso, solo los de las variantes en el segundo. La gravedad es siempre media. El enlace es Ver textos compartibles cuando el informe tiene esa sección, y Ver tipos de llamada cuando no la tiene.

El recuento de grupos del texto cubre todas las formas de SQL con literales del trace, también las que quedan fuera de la sección Textos compartibles, que lista solo las que más tiempo sumaron. Las formas que más pesan reciben además el hallazgo propio de literales en lugar de bind, con el enlace a la sentencia de la forma.

Causa

En el PARSE, la base de datos busca el SQL en la shared pool. Cuando encuentra un cursor que sirve, el parse es liviano (soft parse). Cuando no lo encuentra, hace el hard parse: revisa el texto, los objetos y los permisos y optimiza el plan. El trace marca el hard parse con mis=1 en la línea PARSE. Causas frecuentes, de la más a la menos frecuente:

  • SQL con literales en lugar de bind variables: cada valor diferente genera un texto nuevo, y cada texto nuevo exige hard parse;
  • cursores invalidados: la recolección de estadísticas, un DDL o un GRANT sobre los objetos del SQL dejan el cursor fuera de uso, y la próxima ejecución rehace el parse;
  • shared pool pequeña o fragmentada: los cursores salen de la memoria y hay que cargarlos de nuevo;
  • versiones del mismo cursor: diferencias en el entorno de la sesión o en el tipo y tamaño de los binds crean cursores hijos nuevos.

Solución

  1. Vea si hay sentencias que solo difieren en literales: siga el enlace Ver textos compartibles del hallazgo (Textos compartibles). Si las hay, la corrección es usar bind variables en la aplicación (literales en lugar de bind).
  2. Para encontrar en la base de datos los mismos SQL con literales diferentes, agrupe la shared pool por la firma que ignora los literales:
    select force_matching_signature, count(*) as textos, min(sql_id) as exemplo
      from v$sql
     where force_matching_signature <> 0
     group by force_matching_signature
    having count(*) > 1
     order by textos desc
     fetch first 20 rows only;
  3. Mientras la aplicación no cambia, CURSOR_SHARING=FORCE hace que la base de datos cambie los literales por binds y reduce los hard parse. Es un paliativo y puede cambiar planes: pruébelo antes y prefiera activarlo solo en la sesión de la aplicación.
    alter session set cursor_sharing = force;
  4. Si no hay literales, busque invalidaciones y recargas de los cursores:
    select sql_id, child_number, loads, invalidations, parse_calls, executions
      from v$sql
     order by invalidations desc
     fetch first 20 rows only;
  5. Con muchos cursores hijos del mismo SQL, vea el motivo de cada uno en v$sql_shared_cursor.
  6. La recolección de estadísticas con no_invalidate => false invalida en el momento los cursores que usan el objeto: en producción, elija el horario.

Cómo confirmar

Genere un trace nuevo de la misma operación después del cambio. En Tipos de llamada, en la fila PARSE, Misses debe bajar en relación con la Cantidad, y en el perfil también CPU: PARSE dbcalls. El hallazgo desaparece cuando el hard parse deja de ser la regla y el PARSE de las variantes con literales deja de pesar en el tiempo total.

La primera ejecución después de un reinicio o de una limpieza de la shared pool siempre hace hard parse: mida con la base de datos en uso normal.

En el informe

En el informe de ejemplo, el único PARSE es hard parse, pero un solo PARSE no pesa en la sesión: sin hallazgo. Los enlaces abren las secciones del ejemplo:

Las esperas en la shared pool, como latch: shared pool y cursor: pin S wait on X, entran en la clase Concurrency y tienen página propia: contención por estructuras internas.

Actualizado el 29/10/2026. Informar un error en esta página