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:
- ¿En qué capa es lenta esta consulta: escaneo, shuffle, join, agregación, spill, GC, planificación, arranque en frío?
- ¿Hay sesgo de datos? ¿En qué stage / task / fragmento SQL?
- ¿Qué problemas son de datos y cuáles son de recursos o configuración?
- ¿El siguiente paso debería ser modificar el SQL, ajustar la configuración o reparar los datos?
Prioridad de entrada
| Entrada | Qué se puede hacer |
|---|---|
| URL de UI + ID de Ejecución/Hora de envío + SQL | Lo más completo, diagnóstico a nivel de task |
| Registros de ejecución (con app ID y URL de UI) + SQL | Primero parsear logs, luego acceder a la UI; si la UI no está disponible, degradar a nivel de stage |
| EXPLAIN FORMATTED | Solo mapeo de estructura del plan y fragmentos SQL |
| event log / History Server | Plan 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; /sqlpor 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
executorRunTimevs 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
executorDeserializeTimemuy alto, generalmente un ejecutor en frío; - Spill:
memoryBytesSpilled/diskBytesSpilled, y elspill sizede 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:
- Conclusión primero (ordenada por impacto);
- Resumen de ejecución y línea de tiempo;
- Tabla de evidencia de sesgo / cola larga;
- Mapeo del plan SQL;
- Configuración y riesgos;
- Sugerencias;
- Fuentes de evidencia y limitaciones;
- 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:
-
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. -
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 / durationalta, es un ejecutor en frío, no sesgo de datos. -
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. -
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. -
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. -
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.
-
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,minExecutorsde asignación dinámica, cola de YARN. -
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.