12-twelve-ly/spark-sql-diagnosis

Analiza la ejecución de trabajos de Apache Spark / Spark SQL. Identifica cuellos de botella en consultas lentas, sesgo de datos, spill, GC, problemas de planificación/arranque en frío, expansión de joins y problemas de configuración usando el SQL original, EXPLAIN FORMATTED, logs de Kyuubi/Spark Driver y la URL de Spark UI.

¿Qué es spark-sql-diagnosis?

Esta habilidad (skill) para agentes de IA, como Claude Code o Cursor, automatiza el diagnóstico de rendimiento de trabajos Apache Spark y Spark SQL. Su propósito es ir más allá de la simple revisión de métricas y proporcionar un análisis profundo que identifique las causas raíz de la lentitud: desde sesgo de datos en tareas y desbordamiento a memoria (spill) hasta problemas de planificación del scheduler o de configuración de AQE (Adaptive Query Execution). Soporta múltiples fuentes de entrada: una URL de Spark UI, registros del driver (logs), el plan de ejecución `EXPLAIN FORMATTED`, o incluso archivos event log exportados. El flujo de trabajo es integral: primero recopila y parsea la información, luego la correlaciona con la ejecución real mediante la API REST de Spark, ejecuta un script de diagnóstico (`spark_diagnose.py`) que extrae indicadores clave (distribución de tareas, tiempo de ejecución vs. tiempo de deserialización, patrones de spill), y finalmente genera un informe estructurado en Markdown. El agente utiliza este informe para priorizar hallazgos, mapear operadores del plan a fragmentos SQL, sugerir acciones correctivas (cambiar SQL, ajustar configuración o reparar datos) y, crucialmente, distinguir entre un verdadero sesgo de datos y un simple 'arranque en frío' de ejecutores, evitando diagnósticos erróneos comunes. La habilidad también proporciona reglas de juicio crítico y documentación de referencia para asegurar que el análisis sea preciso y accionable.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add 12-twelve-ly/spark-sql-diagnosis-skill

Installed? Explore more Investigación y análisis de datos skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Diagnóstico de Spark SQL

Cuándo usar

Úsalo cuando el usuario proporcione cualquier combinación de:

  • Una URL de Spark UI / History Server / YARN proxy;
  • Una consulta Spark SQL y su EXPLAIN FORMATTED;
  • Registros de ejecución de Kyuubi / Spark Driver;
  • JSON exportado desde /api/v1/..., o un event log.

El objetivo no es "mirar algunos indicadores", sino responder:

  1. ¿En qué capa es lenta esta consulta: escaneo, shuffle, join, agregación, spill, GC, planificación, arranque en frío?
  2. ¿Hay sesgo de datos? ¿En qué stage / task / fragmento SQL?
  3. ¿Qué problemas son de datos y cuáles son de recursos o configuración?
  4. ¿El siguiente paso debería ser modificar el SQL, ajustar la configuración o reparar los datos?

Prioridad de entrada

EntradaQué se puede hacer
URL de UI + ID de Ejecución/Hora de envío + SQLLo más completo, diagnóstico a nivel de task
Registros de ejecución (con app ID y URL de UI) + SQLPrimero parsear logs, luego acceder a la UI; si la UI no está disponible, degradar a nivel de stage
EXPLAIN FORMATTEDSolo mapeo de estructura del plan y fragmentos SQL
event log / History ServerPlan de respaldo cuando la UI ha expirado

Los logs generalmente ya contienen:

application ID: application_xxx
application web UI: http://host:8088/proxy/application_xxx

Por lo tanto, no es necesario que el usuario pegue la URL de la UI por separado, pero se debe verificar realmente si la URL es accesible.

Flujo de trabajo

1. Recopilar y analizar la entrada

  • Extraer del log: app ID, URL de UI, operation ID, línea de tiempo de stage/job, Final Plan;
  • Extraer del SQL original: nombres de tablas, condiciones de join, group by / distinct / window / order by;
  • Extraer de EXPLAIN FORMATTED: operadores, columnas de entrada/salida, condiciones de join, clave de agregación.

2. Localizar la ejecución real

  • Priorizar el uso del Execution ID;
  • De lo contrario, hacer coincidir por texto SQL + hora de envío en la lista /sql;
  • /sql por defecto solo devuelve unos pocos registros desde offset=0; se debe paginar o sondear por ID;
  • Si hay múltiples candidatos, seleccionar el más reciente y con la descripción que coincida; si aún no es único, preguntar al usuario.

3. Obtener datos de ejecución

Ejecutar el script (recomendado). Los siguientes scripts/ son relativos al directorio de esta habilidad; si se ejecuta en otro directorio, primero haz cd al directorio de la habilidad o usa rutas absolutas.

python scripts/spark_diagnose.py \
  --url "http://host:8088/proxy/application_xxx" \
  --exec-id 94 \
  --sql-file query.sql \
  --explain explain.txt \
  --log run.log \
  --out report.md \
  --json report.json

Si no estás seguro del Execution ID:

python scripts/spark_diagnose.py \
  --url "http://host:18080/history/application_xxx/" \
  --sql-file query.sql \
  --exec-time "2026-11-02T08:06:50Z" \
  --out report.md

Parámetros de autenticación:

--cookie "name=value; name2=value2"
--header "X-Token: ..."
--user "user:password"
--kerberos          # usa curl --negotiate
--insecure          # omite la verificación TLS, solo para certificados autofirmados en redes internas

Principio de solo lectura: el script solo realiza llamadas GET, no ejecuta SQL, no escribe en el clúster.

4. Interpretar las métricas

El script generará JSON estructurado y Markdown. Puntos clave a revisar:

  • Línea de tiempo de stages: tiempo de pared vs executorRunTime vs retardo de inicio de tareas;
  • Distribución de tareas: max/median/p95 de duración, registros, bytes de shuffle;
  • Sesgo real: cuando una tarea tiene tanto registros como duración significativamente por encima de la mediana;
  • Falsa cola larga: número de registros normal, pero executorDeserializeTime muy alto, generalmente un ejecutor en frío;
  • Spill: memoryBytesSpilled / diskBytesSpilled, y el spill size de los nodos del plan;
  • Nodos del plan: filas de salida / bytes de shuffle / duración de Scan, Exchange, Join, Aggregate;
  • Configuración: AQE, umbral de skewJoin, número de particiones de shuffle, umbral de broadcast, asignación dinámica.

5. Escribir el informe final

El script proporciona evidencia y conclusiones candidatas. La respuesta final debe complementarse con la semántica SQL:

  • Mapeo de operadores a fragmentos SQL;
  • Significado comercial de las keys calientes (si se puede inferir del SQL / lógica de creación de tablas);
  • Prioridad de las sugerencias y beneficio esperado;
  • Indicar explícitamente las partes que "requieren verificación externa".

Estructura del informe:

  1. Conclusión primero (ordenada por impacto);
  2. Resumen de ejecución y línea de tiempo;
  3. Tabla de evidencia de sesgo / cola larga;
  4. Mapeo del plan SQL;
  5. Configuración y riesgos;
  6. Sugerencias;
  7. Fuentes de evidencia y limitaciones;
  8. Problemas que aún requieren verificación externa.

Reglas de juicio clave

Estas reglas deben cumplirse para evitar los errores de diagnóstico más comunes:

  1. El sesgo se mide por registros y duración, no solo por bytes de shuffle. Una key caliente altamente comprimible (por ejemplo, muchos item_id=1) puede ocupar solo unos pocos MB, pero representar el 60% de los registros.

  2. Distinguir entre sesgo real y arranque en frío. Si una tarea lenta tiene un número normal de registros y una relación executorDeserializeTime / duration alta, es un ejecutor en frío, no sesgo de datos.

  3. La agregación parcial puede ocultar el sesgo de GROUP BY. Cuando el plan tiene partial_count / partial_sum, la key caliente se comprime en pocas filas antes del shuffle; hay que verificar si la escritura de la agregación evita el sesgo.

  4. count(DISTINCT) es una deduplicación en dos fases. La clave del primer shuffle suele incluir el campo distinct (por ejemplo, (item_id, buyer_id)), por lo que los puntos calientes se distribuyen; no juzgar como un GROUP BY normal.

  5. El AQE skew join se basa en el tamaño. El criterio es el tamaño de la partición comprimida frente a skewedPartitionFactor / skewedPartitionThresholdInBytes; los puntos calientes comprimibles pueden estar por debajo del umbral y no dividirse.

  6. Aumentar el número de particiones de shuffle no diluye una única key caliente. Una key individual siempre va a una partición; cuantas más particiones, más pequeñas son las otras, y el max/mediana aumentan.

  7. Cuando el tiempo de pared de un stage es muy superior al tiempo de ejecución de las tareas, primero revisar la planificación. Mirar launchTime - submissionTime, minExecutors de asignación dinámica, cola de YARN.

  8. Sospechar de expansión solo cuando el número de filas de salida de un join es significativamente mayor que el de entrada. Cuando el número de filas de salida es igual al número de filas de la tabla de hechos, el problema suele ser la distribución, no las claves duplicadas.

Límites

  • No se puede ver el contenido real de los datos; el valor específico de las keys calientes necesita que el usuario consulte los datos;
  • La cola de YARN y la lentitud en la asignación de contenedores requieren logs de RM/Kyuubi;
  • Los problemas de UDF/código personalizado necesitan el código y los logs del executor;
  • Sin UI/event log, los logs normales del driver solo permiten diagnóstico a nivel de stage;
  • No ejecutar SQL, no modificar datos, no imprimir cookies/tokens.

Referencia

  • references/endpoints.md: Endpoints REST y paginación;
  • references/metrics.md: Diferencias de campos y conversión de unidades;
  • references/heuristics.md: Umbrales, plan y determinación de sesgo.

Skills relacionados