Voltar para o blog
Desenvolvimento Fluig4 min de leitura

Dataset sincronizado no Fluig: timeout e lentidão

Sincronização de dataset com timeout no Fluig? Entenda o lastSyncDate em 1969, por que a consulta explode e como resolver com tabelas temporárias.

Datasets sincronizados são a saída natural para relatórios pesados: em vez de rodar a consulta a cada abertura, o Fluig guarda o resultado e atualiza em segundo plano. Funciona bem até o dia em que a sincronização passa a estourar o tempo limite, e o relatório para de atualizar.

Este texto parte de um caso real, em que um cache de relatório financeiro acumulou timeouts seguidos.

Primeiro sinal: lastSyncDate em 1969

Se o log mostra lastSyncDate em dezembro de 1969, não pense "está lento". Essa data é o marco zero do relógio do sistema, ajustado ao fuso. Significa que nunca houve uma execução bem-sucedida.

O Fluig só grava lastSyncDate quando o onSync termina com sucesso. Isso pode criar um ciclo:

  1. A sincronização falha, e a data não é gravada.
  2. Sem data, o script entende que precisa de carga completa.
  3. A carga completa estoura o tempo.
  4. Volta ao passo 1.

Onde o tempo foi parar

O relatório usava uma consulta com CTEs sobre as tabelas de histórico e de tarefas. O diagnóstico revelou duas causas.

Só uma parte da consulta tinha filtro. As CTEs de histórico calculavam ROW_NUMBER() sobre a tabela inteira, de todos os processos do Fluig, para no fim usar apenas as linhas de um processo. A consulta fazia mais de cem vezes o trabalho necessário.

As estatísticas do banco estavam velhas. A tabela tinha crescido muito desde a última atualização. Com uma estimativa errada, o otimizador reservou memória de menos, derramou em disco e ficou lento. Com MAXDOP 1, nem o paralelismo compensava.

O suspeito óbvio, uma subconsulta com FOR XML PATH, não tinha relação com o problema. A tabela era pequena. Por isso a regra: meça antes de reescrever.

A solução: materializar em tabelas temporárias

Em vez de uma grande consulta, divida o trabalho em etapas:

-- Etapa 1: so as solicitacoes do processo
SELECT NUM_PROCES, COD_EMPRESA, START_DATE, END_DATE
INTO #PW
FROM PROCES_WORKFLOW WITH (NOLOCK)
WHERE COD_DEF_PROCES = ?;

CREATE UNIQUE CLUSTERED INDEX IX_PW ON #PW (NUM_PROCES);

-- Etapa 2: historico apenas dessas solicitacoes
SELECT h.NUM_PROCES, h.NUM_SEQ_MOVTO, h.NUM_SEQ_ESTADO,
       ROW_NUMBER() OVER (PARTITION BY h.NUM_PROCES ORDER BY h.NUM_SEQ_MOVTO DESC) AS RN
INTO #HIST_TODOS
FROM HISTOR_PROCES h WITH (NOLOCK)
JOIN #PW p ON p.NUM_PROCES = h.NUM_PROCES;

Isso resolve as duas causas de uma vez. O filtro chega antes do cálculo, e o otimizador passa a ter a contagem exata de linhas, sem depender das estatísticas das tabelas nativas.

Há mais um ganho: cada etapa roda em um comando separado, com tempo próprio no log. Assim, você enxerga exatamente qual etapa pesa. Essas tabelas temporárias existem na sessão da conexão, portanto mantenha a mesma conexão entre as etapas.

Cuidado com a carga incremental

Atualizar só o que mudou parece sempre melhor. Em nosso caso, foi o contrário: depois da correção, a carga completa ficou em poucos segundos, enquanto a incremental continuava estourando o tempo.

O motivo era um filtro com três condições em OR, uma delas um EXISTS na tabela de histórico. OR impede o banco de usar bem os índices, e a estimativa errada completava o estrago.

A decisão foi simples: desligar o incremental. Se a carga completa é rápida, a complexidade do delta não se paga. Antes de mantê-lo, compare os dois com números.

Roteiro de diagnóstico

  1. Procure lastSyncDate e o erro da última execução no server.log.
  2. Rode a consulta manualmente, medindo cada etapa.
  3. Compare as linhas processadas com as linhas realmente usadas.
  4. Veja o plano de execução e a estimativa de linhas.
  5. Filtre o mais cedo possível, antes de qualquer função de janela.
  6. Divida em etapas e registre o tempo de cada uma no log.
  7. Depois de corrigir, confirme que lastSyncDate foi gravada.

Atualizar estatísticas pode ajudar, mas tabelas nativas do Fluig são da plataforma. Trate isso com o responsável pelo banco, e prefira uma consulta que não dependa disso.

Quando o relatório não acessa tabelas de formulário, às vezes nem precisa de cache. Um painel de SLA por SQL, por exemplo, costuma ser leve o bastante para rodar direto.

Se o log mostrar outras causas de lentidão, siga o roteiro de como investigar um Fluig lento.

Perguntas frequentes

O que significa lastSyncDate 1969 no Fluig?

Que a sincronização nunca terminou com sucesso. É o valor inicial da data, não uma execução antiga.

Por que o dataset sincronizado dá timeout?

Em geral, por uma consulta que processa mais dados do que precisa. Tabelas de histórico crescem rápido, e consultas sem filtro no começo sofrem primeiro.

Vale a pena usar sincronização incremental?

Só se a carga completa for lenta de verdade e o filtro do delta usar bem os índices. Meça os dois caminhos.

Relatórios lentos costumam esconder consultas que dá para resolver. Veja como a MyQube trabalha com dashboards para Fluig e Protheus ou fale com a gente.

Sua operação ainda depende de planilhas e retrabalho?

Agende uma conversa gratuita e receba um diagnóstico inicial dos seus gargalos operacionais.

Falar com a MyQube

Ou conheça nosso serviço de Consultoria Fluig