Problemas de memoria de Spark

Cuando los ejecutores se quedan sin memoria, Spark los elimina y vuelve a intentar sus tareas. El trabajo se ralentiza y, tras varios errores, la fase y el trabajo producen un error.

Utiliza esta página cuando fallen los trabajos o se eliminen ejecutores y el registro de eventos del cómputo no muestre pérdidas de instancias spot o preemptibles ni autoescalado. Para consultar el registro de eventos, consulte Trabajos fallidos o ejecutores eliminados. Si la fase termina pero es lenta y muestra spill, véase Skew and spill.

Comprobación de un problema de memoria

Los problemas de memoria suelen causar errores como:

SparkException: Job aborted due to stage failure: Task 3 in stage 0.0 failed 4 times, most recent failure: Lost task 3.3 in stage 0.0 (TID 30) (10.139.64.114 executor 4): ExecutorLostFailure (executor 4 exited caused by one of the running tasks) Reason: Remote RPC client disassociated. Likely due to containers exceeding thresholds, or network issues. Check driver logs for WARN messages.

Estos errores suelen ser genéricos y otros problemas pueden causarlos. Si sospechas que hay un problema de memoria, verifica duplicando la memoria por núcleo para ver si se resuelve el problema.

Por ejemplo, si el tipo worker tiene 4 núcleos y 16 GB de memoria, cambia a un tipo worker con 4 núcleos y 32 GB de memoria. Eso te da 8 GB por núcleo en lugar de 4 GB. La proporción de memoria respecto a núcleos importa, no la memoria total. Si el trabajo tarda más en fallar o no falla en absoluto, la memoria podría ser la causa.

Si más memoria soluciona el problema, mantén el tipo de worker más grande. Si no es así, o si el coste extra es demasiado alto, revisa las posibles causas en la siguiente sección.

Causas posibles

Los problemas de memoria tienen muchas causas posibles. Empieza por estas causas comunes:

  • Muy pocas particiones de orden aleatorio. Establezca spark.sql.shuffle.partitions en auto para que Spark elija el número de particiones de orden aleatorio. Ver configuración AQE.
  • Una difusión de gran tamaño. Compruebe si hay sugerencias de combinación de difusión en tablas grandes y revise el umbral de difusión en tiempo de ejecución. Ver configuración AQE.
  • UDFs. Cada tarea que ejecuta una UDF puede cargar todos los datos de su partición en la memoria. Reescribe el UDF usando funciones nativas, o vuelve a particionar antes de aplicarlo. Véase UDFs lentos.
  • Una función ventana sin PARTITION BY. Añade una PARTITION BY cláusula para que la ventana no abarque todo el conjunto de datos. Consulte Fase de Spark larga con una sola tarea.
  • Sesgo. Verifica el sesgo en las Métricas Resumen de la etapa. Véase Skew. Para las combinaciones, consulte Control dinámico de la combinación sesgada.
  • Estado de streaming. Para consultas que mantienen el estado de streaming, usa el almacén de estados RocksDB y limita su uso de memoria. Consulte Uso de memoria de Cap RocksDB.