Diagnóstico Spark SQL
Quando usar
Use quando o usuário fornecer qualquer combinação do seguinte:
- Uma URL do Spark UI / History Server / YARN proxy;
- Uma consulta Spark SQL e seu
EXPLAIN FORMATTED; - Logs de execução do Kyuubi / Spark Driver;
- JSON exportado de
/api/v1/...ou event log.
O objetivo não é "olhar algumas métricas", mas responder:
- Em qual camada esta consulta está lenta: scan, shuffle, join, agregação, spill, GC, escalonamento, inicialização a frio;
- Há skew de dados? Em qual stage / task / fragmento SQL;
- O que é problema de dados e o que é problema de recurso ou configuração;
- Qual deve ser o próximo passo: alterar SQL, alterar configuração ou corrigir dados.
Prioridade de entrada
| Entrada | O que pode fazer |
|---|---|
| URL da UI + ID de execução/horário de submissão + SQL | Mais completo, diagnóstico no nível de task |
| Logs de execução (com app ID e URL da UI) + SQL | Primeiro analisa os logs, depois acessa a UI; quando a UI não está disponível, degrada para diagnóstico no nível de stage |
| EXPLAIN FORMATTED | Apenas mapeamento da estrutura do plano e fragmentos SQL |
| event log / History Server | Plano de contingência quando a UI expirou |
Os logs geralmente já contêm:
application ID: application_xxx
application web UI: http://host:8088/proxy/application_xxx
Portanto, não é necessário que o usuário cole novamente a URL da UI, mas é obrigatório verificar se o endereço está acessível.
Fluxo de trabalho
1. Coletar e analisar entrada
- Extrair do log: app ID, URL da UI, operation ID, timeline de stage/job, plano final;
- Extrair do SQL original: nomes de tabelas, condições de join, group by / distinct / window / order by;
- Extrair do
EXPLAIN FORMATTED: operadores, colunas de entrada/saída, condições de join, chaves de agregação.
2. Localizar a execução real
- Priorizar o uso do Execution ID;
- Caso contrário, combinar pela consulta SQL e horário de submissão na lista
/sql; - A lista
/sqlretorna apenas alguns registros a partir de offset=0 por padrão; é necessário paginar ou sondar por ID; - Se houver múltiplos candidatos, selecionar o mais recente cuja descrição corresponda; se ainda não for único, perguntar ao usuário.
3. Obter dados de execução
Execute o script (recomendado). Os scripts/ abaixo são relativos ao diretório desta skill; se executar em outro diretório, cd para o diretório da skill ou use caminhos absolutos.
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
Se não tiver certeza do 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 autenticação:
--cookie "name=value; name2=value2"
--header "X-Token: ..."
--user "user:password"
--kerberos # usar curl --negotiate
--insecure # pular validação TLS, apenas para certificados autoassinados em rede interna
Princípio de somente leitura: o script faz apenas chamadas GET, não executa SQL, não escreve no cluster.
4. Interpretar métricas
O script gera JSON estruturado e Markdown. Foco principal:
- Timeline de stages: wall clock vs
executorRunTimevs atraso de inicialização de tasks; - Distribuição de tasks: max/mediana/p95 de duration, records, shuffle bytes;
- Skew verdadeiro: records e duration de uma task significativamente acima da mediana;
- Long tail falso: número de registros normal, mas
executorDeserializeTimemuito alto, geralmente executor frio; - Spill:
memoryBytesSpilled/diskBytesSpilled, espill sizeno nó do plano; - Nós do plano: output rows / shuffle bytes / duration de Scan, Exchange, Join, Aggregate;
- Configuração: AQE, limites de skewJoin, número de partições shuffle, limite de broadcast, alocação dinâmica.
5. Escrever relatório final
O script fornece evidências e conclusões candidatas. A resposta final deve complementar com base na semântica SQL:
- Operador → mapeamento de fragmento SQL;
- Significado de negócio da chave quente (se puder inferir do SQL/lógica de criação de tabela);
- Prioridade da sugestão e ganho esperado;
- Marcar explicitamente o que precisa de "validação externa".
Estrutura do relatório:
- Conclusão primeiro (ordenada por impacto);
- Visão geral da execução e timeline;
- Tabela de evidências de skew/long tail;
- Mapeamento do plano SQL;
- Configuração e riscos;
- Sugestões;
- Fontes de evidência e limitações;
- Questões que ainda precisam de validação externa.
Regras de julgamento críticas
Estas regras devem ser seguidas para evitar os erros de diagnóstico mais comuns:
-
Skew: olhe records e duration, não apenas shuffle bytes. Uma chave quente altamente compressível (por exemplo, muitos
item_id=1) pode ocupar apenas alguns MB, mas representar 60% dos registros. -
Distinguir skew verdadeiro de inicialização a frio. Se uma task lenta tem número de registros normal e
executorDeserializeTime / durationalto, é executor frio, não skew de dados. -
Agregação parcial pode mascarar skew de GROUP BY. Quando o plano tem
partial_count/partial_sum, a chave quente é comprimida em poucas linhas antes do shuffle; verificar se a própria escrita da agregação evita o skew. -
count(DISTINCT)é uma desduplicação em dois estágios. A chave do primeiro shuffle geralmente inclui o campo distinct (ex.:(item_id, buyer_id)), e os pontos quentes são espalhados; não julgar como GROUP BY comum. -
Skew join do AQE é baseado em tamanho. O critério é o tamanho da partição após compressão comparado com
skewedPartitionFactor/skewedPartitionThresholdInBytes; chaves quentes compressíveis podem ficar abaixo do limite e não serem divididas. -
Aumentar o número de partições shuffle não dilui uma única chave quente. Uma chave sempre vai para a mesma partição; quanto mais partições, menor fica a mediana, mas o máximo permanece o mesmo.
-
Quando o wall clock do stage for muito maior que o tempo de execução das tasks, verifique o escalonamento primeiro. Olhe
launchTime - submissionTime,minExecutorsda alocação dinâmica, fila do YARN. -
Só suspeite de inchaço de join quando o número de linhas de saída for significativamente maior que o de entrada. Se as linhas de saída forem iguais ao número de linhas da tabela fato, o problema geralmente é distribuição, não chaves duplicadas.
Limitações
- Não é possível ver o conteúdo real dos dados; o valor específico da chave quente requer consulta do usuário aos dados;
- A causa exata da fila do YARN ou alocação lenta de contêineres requer logs do RM/Kyuubi;
- Problemas de UDF/código personalizado requerem código e logs do executor;
- Sem UI/event log, logs comuns do driver só permitem diagnóstico no nível de stage;
- Não executa SQL, não modifica dados, não imprime cookies/tokens.
Referências
references/endpoints.md: Endpoints REST e paginação;references/metrics.md: Diferenças de campos e conversão de unidades;references/heuristics.md: Limiares, planos e julgamento de skew.