Todos os produtos
Search
Central de documentação

MaxCompute:Casos de diagnóstico do LogView

Última atualização: Aug 21, 2026

Na maioria dos casos, as empresas precisam que os resultados dos jobs sejam gerados antes do previsto para tomar decisões de negócios o mais rápido possível. Nesse cenário, os desenvolvedores devem monitorar o status dos jobs para identificar e otimizar aqueles com execução lenta. O LogView do MaxCompute permite diagnosticar jobs com desempenho abaixo do esperado. Este tópico apresenta as causas de execuções lentas e as respectivas soluções, além de descrever como visualizar informações sobre esses jobs.

Diagnosticar um job com falha na execução

Quando um job falha, consulte as informações de erro na aba result no LogView. Para jobs com falha, o LogView abre a aba result por padrão.

Causas possíveis:

  • Sintaxe SQL incorreta. Nesse caso, não há grafo acíclico direcionado (DAG) nem job Fuxi, pois o job não foi enviado ao cluster de computação para execução.

  • Erros em uma função definida pelo usuário (UDF). Visualize o DAG na aba job details para identificar a UDF problemática e verifique as mensagens de erro em StdOut ou StdError.

  • Outros erros. Para mais informações sobre outros tipos de erro, consulte Error code overview.

Diagnosticar um job com execução lenta

Estágio de compilação

Um job no estágio de compilação possui um LogView, mas ainda não tem um plano de execução. Essa fase inclui subestágios como agendamento, otimização, geração do plano de execução física e replicação de dados entre clusters. A aba SubStatusHistory lista o código de status (Code), a descrição (Description), o horário de início e a latência de cada subestágio. Um problema comum durante a compilação é o travamento do job, quando ele permanece em um único subestágio por um período prolongado. As seções a seguir descrevem as possíveis causas e soluções para jobs travados em cada subestágio.

  • Agendamento

    Descrição do problema: O substatus do job é Waiting for cluster resource. O job aguarda compilação.

    Causa: Recursos insuficientes no cluster de computação.

    Solução: Verifique o status e os recursos necessários do cluster de computação. Se você utiliza um cluster por assinatura, aumente a capacidade dos recursos.

  • Otimização

    Descrição do problema: O substatus do job é SQLTask is optimizing query. O otimizador está ajustando o plano de execução.

    Causa: O plano de execução é complexo. O otimizador precisa de muito tempo para concluir o ajuste.

    Solução: Aguarde a conclusão da otimização. Na maioria dos casos, esse processo leva menos de 10 minutos.

  • Geração do plano de execução

    Descrição do problema: O substatus do job é SQLTask is generating execution plan.

    Causa 1: Leitura de dados de um número excessivo de partições.

    Solução: Otimize as instruções SQL para reduzir o número de partições. Por exemplo, aplique poda de partições, filtre partições desnecessárias e divida jobs grandes em menores. Para saber como verificar se a poda de partições está ativa em instruções SQL e conhecer cenários comuns de falha nesse recurso, consulte Check whether partition pruning is effective.

    Causa 2: Geração excessiva de arquivos pequenos. Arquivos pequenos são gerados nos seguintes cenários:

    1. Operação incorreta ao usar comandos Tunnel para upload de dados. Por exemplo, criar uma nova upload session para cada registro de dados carregado. Para mais informações, consulte FAQ about Tunnel commands.

    2. Execução de uma operação insert into em uma tabela particionada gera um novo arquivo no diretório da partition.

    Soluções

    1. Utilize a interface TunnelBufferedWriter para carregar dados de forma mais eficiente e evitar a geração excessiva de arquivos pequenos.

    2. Mescle manualmente os arquivos pequenos. Para mais detalhes, consulte Merge small files.

    Nota

    Se houver mais de 10.000 arquivos pequenos, ative a mesclagem automática. O sistema mesclará os arquivos diariamente. No entanto, se a mesclagem automática falhar em cenários específicos, será necessário realizar a mesclagem manual.

  • Replicação de dados entre clusters

    Sintoma: A lista de substatus exibe várias instâncias de Task rerun, e a aba Result mostra a mensagem de erro FAILED: ODPS-0110141:Data version exception. O job pode parecer ter falhado, mas continua em execução, indicando replicação de dados entre clusters.

    Causa 1: Migração de dados entre clusters do projeto. Nesse caso, muitos jobs de replicação entre clusters são executados nos primeiros um ou dois dias após a conclusão da migração.

    Solução: Aguarde a conclusão esperada da replicação de dados entre clusters.

    Causa 2: Migração de dados entre clusters do projeto sem a filtragem adequada das partições. Isso resulta na leitura de dados antigos de certas partições.

    Solução: Filtre as partições que contêm dados antigos.

Estágio de execução

A página job details no LogView exibe um plano de execução incompleto e o status do job permanece como Running. Durante a execução, o job pode travar ou demorar mais que o esperado devido a espera por recursos, skew de dados, execução ineficiente de UDFs ou expansão de dados. As seções a seguir detalham os sintomas e soluções para cada cenário.

  • Espera por recursos

    Sintoma: Instâncias no estado Ready, ou algumas Running enquanto outras estão Ready. Observe que, se uma instância estiver Ready mas tiver histórico de Debug, ela pode estar tentando novamente após uma falha, e não aguardando recursos. Na lista de instâncias Fuxi, filtre por status usando SmartFilter. A coluna Status indica o estado atual de cada instância.

    Solução:

    1. Verifique se a fila é normal. Consulte a posição do job na fila verificando o Queue Length no painel Basic Info à esquerda do LogView. Alternativamente, verifique o uso de recursos do grupo de cotas correspondente no console do MaxCompute. No painel de navegação à esquerda do console do MaxCompute, escolha Project Management > Quota Management > Resource Consumption para visualizar gráficos de tendências de métricas como CPU Resource do grupo de cotas alvo. Se o uso de um recurso estiver próximo ou acima da cota, o grupo enfrenta escassez de recursos e a formação de fila é normal. A ordem de agendamento depende não apenas do horário de envio e da prioridade, mas também da disponibilidade de memória ou CPU necessários.

    2. Visualize os jobs que utilizam o grupo de cotas.

      Jobs grandes com baixa prioridade podem ter sido enviados, ou múltiplos jobs pequenos foram submetidos simultaneamente, ocupando muitos recursos. Entre em contato com o proprietário desses jobs para encerrá-los e liberar os recursos ocupados.

    3. Altere o grupo de cotas do job para um grupo de outro projeto.

    4. Aumente a capacidade dos recursos. Esta solução aplica-se apenas a usuários com recursos por assinatura.

  • Skew de dados

    Sintoma: A maioria das instâncias de uma tarefa terminou, mas algumas instâncias "long-tail" continuam em execução. Essas instâncias rodam lentamente, possivelmente por processarem um volume maior de dados. No SmartFilter, verifique a contagem de Long-Tails e compare a duração de cada instância na coluna Latency.

    Solução: Para mais informações sobre causas comuns de skew de dados e métodos de otimização relacionados, consulte Data skew tuning.

  • Execução ineficiente de UDF

    Neste tópico, UDFs referem-se a várias extensões definidas pelo usuário, incluindo funções escalares (UDFs), funções agregadas (UDAFs), funções tabulares (UDTFs), joins definidos pelo usuário (UDJs) e tipos definidos pelo usuário (UDTs).

    Descrição: A eficiência de execução de uma tarefa é baixa e a tarefa inclui UDFs. Pode aparecer a seguinte mensagem de erro indicando timeout na execução da UDF: Fuxi job failed - WorkerRestart errCode:252,errMsg:kInstanceMonitorTimeout, usually caused by bad udf performance.

    Solução de problemas: Quando uma tarefa falha, determine rapidamente se ela contém uma UDF examinando o DAG na aba job details no LogView. No DAG, uma tarefa com falha aparece em vermelho, e um rótulo fx como ["JAVA"] no nó indica a linguagem da UDF. Por exemplo, a tarefa com falha R4_3 pode conter uma UDF escrita em Java. Clique duas vezes em R4_3 para abrir a visualização Operator, que lista todas as UDFs naquela tarefa. A visualização Operator exibe a cadeia de operadores de cima para baixo, com uma lista de todas as UDFs referenciadas na parte inferior. Além disso, o log StdOut da tarefa mostra a contagem de registros de entrada, saída e o tempo de processamento da UDF. Esses dados ajudam a identificar problemas de desempenho. Normalmente, uma Speed(records/s) na casa das centenas de milhares ou milhões é normal. Se cair para dezenas de milhares, provavelmente há um problema de desempenho. O log exibe um resumo do processamento da UDF e uma tabela estatística com OutputCount, InnerTime e Speed(records/s) para cada operador (CursorId).

    Solução: Em caso de problema de desempenho, utilize os métodos abaixo para solucionar e otimizar.

    1. Verifique se há erros na UDF.

      Em alguns casos, o problema de desempenho é causado por um valor de dado específico. Por exemplo, um loop infinito ocorre quando um determinado valor aparece. O MaxCompute Studio permite baixar amostras específicas de dados de uma tabela e usá-las localmente para solução de problemas. Para mais informações, consulte Java UDFs e Python UDF no manual de desenvolvimento do MaxCompute Studio.

    2. Verifique se o nome da UDF coincide com o de uma função integrada.

      Uma função integrada pode ser sobrescrita por uma UDF com o mesmo nome. Se uma função parecer ser integrada, confirme se existe alguma UDF homônima capaz de sobrescrevê-la.

    3. Substitua a UDF por uma função integrada.

      Se existirem funções integradas com funcionalidades similares, evite usar UDFs. Funções integradas são validadas e executadas de maneira mais eficiente. Além disso, otimizadores realizam testes white-box nessas funções, permitindo mais otimizações. Para mais informações sobre o uso de funções integradas, consulte Built-in functions.

    4. Substitua UDFs específicas por funções integradas equivalentes e mantenha apenas as UDFs cuja lógica não possa ser implementada com funções nativas.

    5. Otimize o método evaluate das UDFs.

      Use o método evaluate apenas para operações necessárias relacionadas aos parâmetros. Realize inicializações ou cálculos repetitivos antecipadamente, pois o método evaluate é executado reiteradamente.

    6. Estime o tempo necessário para executar uma UDF.

      Simule localmente o volume de dados processado por uma única instância para testar o tempo de execução da UDF. Em seguida, otimize sua implementação. Por padrão, o tempo máximo de execução de uma UDF é de 30 minutos. Uma UDF deve retornar dados dentro desse prazo ou usar context.progress() para enviar heartbeats. Se o tempo estimado exceder 30 minutos, configure um parâmetro para definir o timeout da UDF.

      Default value: 1800. Unit: seconds. Valid values: 1 to 3600.
      -- Specify the timeout period of a UDF. Unit: seconds. Default value: 600.
      -- You can manually adjust the timeout period of the UDF in the range of [0,3600].
    7. Modifique os parâmetros de memória.

      A baixa eficiência de UDFs nem sempre decorre da complexidade computacional. A complexidade de armazenamento também pode afetar o desempenho. Exemplos:

      • Estouro de memória ocorre quando uma UDF realiza computação em memória ou ordena um grande volume de dados.

      • Memória insuficiente causa alta frequência de coleta de lixo (GC).

      Modifique os parâmetros de memória para contornar temporariamente esses problemas. A otimização definitiva deve basear-se nos requisitos do seu negócio. Exemplo:

      set odps.sql.udf.jvm.memory=
      -- Specify the maximum memory size that can be used for the JVM heap of a UDF. Default value: 1024. Unit: MB.
      -- You can change the value of the odps.sql.udf.jvm.memory parameter in the range of [256,12288].
      Nota

      O uso de UDFs pode invalidar a poda de partições. A anotação UdfProperty é suportada a partir do MaxCompute V2.0. Ao definir uma UDF, use essa anotação para indicar ao compilador que a função é determinística. Código de exemplo:

      @com.aliyun.odps.udf.annotation.UdfProperty(isDeterministic = true)
      public class AnnotatedUdf extends com.aliyun.odps.udf.UDF {
          public String evaluate(String x) {
              return x;
          }
      }

      Ao reescrever a instrução SQL de uma UDF, é possível utilizá-la na filtragem de partições.

      -- SQL statement before rewriting
      SELECT * FROM t WHERE pt = udf('foo');  -- pt indicates a partition key column of t.
      -- SQL statement after rewriting
      SELECT * FROM t WHERE pt = (SELECT udf('foo')); --pt indicates a partition key column of t.
  • Expansão de dados

    Sintoma: Os dados de saída de uma tarefa são muito maiores que os de entrada. Por exemplo, se 1 GB de dados se transforma em 1 TB após o processamento, o desempenho de uma instância lidando com 1 TB será severamente degradado. Após a conclusão do job, os I/O Records da tarefa mostram os volumes de entrada e saída. Se um job travar no estágio Join, selecione algumas instâncias Running usando SmartFilter e verifique seus logs StdOut clicando no ícone StdOut. Se o log StdOut mostrar continuamente registros Merge join cursor e o valor de OutputRowCount continuar aumentando, isso indica uma grave expansão de dados. Verifique se a condição JOIN e a chave de junção são adequadas.

    Solução:

    • Verifique no código: se a condição JOIN está correta, se foi escrita como um product cartesiano, se a UDTF está funcionando normalmente e se há geração excessiva de dados de saída.

    • Verifique se a expansão é causada por agregação.

      A maioria dos agregadores executa agregação recursiva. Durante esse processo, primeiro há a fusão dos resultados intermediários. Como o volume desses dados intermediários geralmente é pequeno e a complexidade computacional é baixa, a agregação conclui rapidamente mesmo com grandes volumes de dados. Na maioria dos casos, não ocorre expansão durante a agregação. Contudo, a expansão pode acontecer nos seguintes cenários:

      • Ativação de agregação na instrução SELECT para realizar operações DISTINCT em diferentes dimensões. Os dados expandem a cada operação DISTINCT executada.

      • Ao usar a instrução GROUPING SETS ou CUBE | ROLLUP, o tamanho dos dados de resultado intermediário pode aumentar várias vezes em relação ao original. Porém, ao utilizar instruções específicas como COLLECT_LIST ou MEDIAN, todos os dados intermediários devem ser retidos, o que pode causar problemas específicos.

    • Evite expansão de dados causada por operações JOIN.

      Por exemplo, ao juntar duas tabelas onde a tabela esquerda contém um grande volume de dados populacionais (processados eficientemente devido ao alto paralelismo do MaxCompute) e a tabela direita é uma tabela de dimensões com informações sobre gêneros (apenas dois gêneros, mas centenas de linhas para cada). Juntar as tabelas por gênero pode expandir os dados da tabela esquerda centenas de vezes. Para evitar essa expansão, agrupe as linhas da tabela direita em apenas duas linhas antes de realizar o JOIN.

    • Verifique se a expansão é causada pela instrução GROUPING SET. Durante sua execução, os dados são expandidos e a saída aumenta múltiplas vezes em relação ao número de grupos. O plano de execução atual não consegue adaptar-se automaticamente ao GROUPING SET ou alterar o grau de paralelismo das tarefas subsequentes. Configure manualmente o paralelismo das tarefas downstream. Instruções de exemplo:

      set odps.stage.reducer.num = xxx; 
      set odps.stage.joiner.num = xxx;

Estágio de finalização

A maioria dos jobs SQL para assim que o job Fuxi termina. No entanto, às vezes o status permanece como Running mesmo após o fim do job Fuxi. No LogView, a página Job Details à direita mostra todos os estágios do job Fuxi como Terminated, mas o Status do job no painel esquerdo continua Running e a barra de Progress marca 0%. Isso pode ocorrer por dois motivos:

  1. O job SQL inclui múltiplos jobs Fuxi. Por exemplo, subconsultas executadas em vários estágios ou jobs de mesclagem automática de arquivos disparados devido à geração excessiva de arquivos pequenos.

  2. No estágio de finalização, o job SQL passa muito tempo no cluster de controle. Por exemplo, atualizando metadados de partições dinâmicas. A seção a seguir apresenta exemplos de cenários comuns.

  • Execução de subconsultas em múltiplos estágios

    Geralmente, subconsultas do MaxCompute SQL são compiladas no mesmo DAG Fuxi. Assim, todas as subconsultas e consultas principais são concluídas em um único job Fuxi. Entretanto, certas subconsultas especiais precisam ser executadas separadamente antes das consultas principais. Código de exemplo:

    SELECT
         product,
        sum(price)
     FROM
         sales
     WHERE
         ds in (SELECT DISTINCT ds FROM t_ds_set)
     GROUP BY product;

    A subconsulta SELECT DISTINCT ds FROM t_ds_set é executada primeiro, e seu resultado é necessário para a poda de partições, otimizando o número de partições lidas pela consulta principal. Essas duas execuções são jobs Fuxi separados. No LogView, cada job Fuxi aparece em uma aba distinta, como SQL_0_0_0_job_0 e SQL_0_0_1_job_1. O DAG também mostra as dependências entre múltiplos nós JOB. Basta clicar na segunda tab para ver o status de execução do job_1. Após alternar, você verá o status atual (como Running ou Waiting) de cada tarefa no job_1.

  • Excesso de arquivos pequenos

    O excesso de arquivos pequenos afeta principalmente o desempenho de armazenamento e computação.

    • Armazenamento: Muitos arquivos pequenos aumentam a carga no Apsara Distributed File System, impactando o uso do armazenamento.

    • Computação: O desempenho geral é afetado porque o MaxCompute processa um único arquivo grande de forma mais eficiente do que múltiplos arquivos pequenos. Portanto, ao concluir um job SQL, a operação de mesclagem de arquivos é acionada automaticamente se certas condições forem atendidas, prevenindo a geração excessiva de arquivos pequenos.

  • Se houver excesso de arquivos pequenos, instruções SELECT podem demorar muito durante o estágio de finalização. Para gerar e exibir os resultados, o sistema precisa abrir muitos arquivos pequenos para leitura, um processo demorado. Para evitar a geração massiva de resultados de execução, recomenda-se não usar instruções SELECT diretamente; utilize comandos Tunnel para baixe os dados. Se o volume de resultados não for grande, mas a quantidade de arquivos for excessiva, verifique se o parâmetro odps.merge.smallfile.filesize.threshold está configurado corretamente. Para mais detalhes sobre mesclagem de arquivos, consulte Merge small files.

    Solução: Verifique no LogView se o job acionou uma mesclagem automática de arquivos pequenos. Assim como em multi-stage subquery execution, o job de mesclagem aparece em uma aba separada. O nome da aba pode ser algo como SQL_0_0_0_merge, mostrando o progresso da MergeTask. Embora isso aumente o tempo total de execução, resulta em um número e tamanho de arquivos mais adequados na tabela de saída, aliviando a pressão no sistema de arquivos e melhorando a performance de leitura em jobs futuros.

  • Atualização de metadados em partições dinâmicas

    Descrição do problema: Após a conclusão de um job Fuxi, podem ser necessárias operações específicas de metadados. Por exemplo, mover dados resultantes para um diretório específico e atualizar os metadados da tabela pode gerar muitas partições durante o particionamento dinâmico, tornando o processo demorado. Suponha que a instrução insert into ... values seja executada na tabela particionada sales para adicionar 2.000 partições. Instrução de exemplo:

    INSERT INTO TABLE sales partition (ds)(ds, product, price)
    VALUES ('20170101','a',1),('20170102','b',2),('20170103','c',3), ...;

    Após o término do job Fuxi, ainda leva tempo para atualizar os metadados da tabela. O SubStatusHistory do LogView mostra que o job está parado em SQLTask is updating meta information. Isso corresponde ao código de status 1260; verifique o valor de Latency para saber quanto tempo a atualização levou.

  • Aumento no tamanho do arquivo de saída

    Sintoma: Os dados podem expandir várias vezes mesmo que os números de registros de entrada e saída sejam semelhantes. Na coluna IO Bytes dos Fuxi Jobs, compare os tamanhos de Input e Output de cada Task para identificar em qual estágio ocorreu a expansão.

    Solução: Uma causa é a mudança na distribuição dos dados, afetando a compressão. Durante a gravação na tabela, os dados são comprimidos. Algoritmos de compressão atingem taxas maiores em dados repetitivos. Logo, agrupar dados idênticos durante a gravação melhora a compressão. A distribuição depende fortemente de como os dados são embaralhados e ordenados na etapa de escrita (R12 nos Fuxi Jobs). Neste exemplo, a operação SQL final é um JOIN com a seguinte chave:

    on  t1.query = t2.query and t1.item_id=t2.item_id

    As características dos dados indicam que a maioria das colunas são atributos dos itens. Assim, todas as colunas para itens com o mesmo item_id são idênticas. No entanto, os itens na consulta estão ordenados aleatoriamente, causando baixa taxa de compressão. O código abaixo mostra como modificar a sequência do JOIN. Após a alteração, o tamanho dos dados reduziu para 1/3 do original.

    on t1.item_id=t2.item_id and t1.query = t2.query

    Após a modificação, o tamanho dos dados diminuiu para 1/3 do original.

    Em outro caso, as operações de shuffle geradas por JOIN ou GROUP BY não contêm a coluna de ordenação ideal para compressão. Nesse cenário, use a cláusula ZORDER BY para ordenar os itens localmente e obter alta compressão a um custo menor. Também é possível executar uma instrução DISTRIBUTED BY SORT BY para reorganizar manualmente a distribuição. Esse método exige mais tempo de cálculo e alto uso de CPU.