Como os operadores atualizam incrementalmente

A tabela a seguir descreve como cada operador é incrementalizado (ou seja, como ele é transformado em um novo fragmento de consulta que gera alterações em vez de resultados completos) e seu desempenho e outros fatores importantes a serem considerados.

Operador

Incrementalização

Considerações

SELECT <expressões escalares>

Incrementalizado pela aplicação de expressões a linhas alteradas.

Tem bom desempenho, sem considerações especiais.

WHERE <expressões escalares>

Incrementalizado avaliando o predicado em cada linha alterada e incluindo apenas aquelas para as quais o predicado é verdadeiro.

Geralmente tem bom desempenho. O custo é escalonado linearmente com o tamanho das mudanças.

Atualizando uma tabela dinâmica com uma expressão WHERE altamente seletiva pode exigir tempo de atividade do warehouse, mesmo que a tabela dinâmica resultante não mude. Isso ocorre porque um warehouse pode ser necessário para determinar quais alterações nas fontes satisfazem o predicado.

FROM <tabela base>

Incrementalizado pela verificação de micropartições que foram adicionadas ou removidas da tabela desde a última atualização.

O custo é escalonado linearmente com o volume de dados nas micropartições adicionadas ou removidas.

Recomendações:

  • Limite o volume de alterações por atualização a cerca de 5% da tabela de origem.

  • Seja cauteloso com DMLs que afetam muitas micropartições.

<consulta> UNION ALL <consulta>

Incrementalizado pela união de todas as alterações em cada lado.

Tem bom desempenho, sem considerações especiais.

WITH <lista CTE><consulta>

Incrementalizado pelo cálculo das alterações de cada expressão de tabela comum.

WITH torna consultas complexas mais fáceis de ler, mas tenha cuidado para não tornar a definição de uma única tabela dinâmica muito complexa. Para obter mais informações, consulte Como encadear pipelines de tabelas dinâmicas e Otimização do desempenho do modo de atualização incremental para tabelas dinâmicas complexas.

Agregados escalares

Atualmente, os agregados escalares não são incrementalizados de forma eficiente. Quando a entrada deles muda, eles são totalmente recalculados.

GROUP BY <chaves>

Incrementalizado pela recomputação de agregados para cada chave de agrupamento que mudou.

Garanta que os dados de origem sejam clusterizados pelas chaves de agrupamento e que as alterações compreendam uma pequena fração (aproximadamente < 5%) das chaves de agrupamento.

Se a chave de agrupamento contiver uma expressão composta em vez de uma coluna base, atualizações incrementais poderão ter que verificar uma grande quantidade de dados. Para reduzir o tamanho dessas verificações, materialize a expressão em uma tabela dinâmica e, em seguida, aplique a operação de agrupamento na coluna materializada em outra tabela dinâmica.

Por exemplo, considere a seguinte instrução composta:

CREATE DYNAMIC TABLE sums
  AS
    SELECT date_trunc(minute, ts), sum(c1) FROM table
    GROUP BY 1;
Copy

A instrução acima pode ser otimizada da seguinte forma:

CREATE DYNAMIC TABLE intermediate
  AS
    SELECT date_trunc(minute, ts) ts_min, c1 FROM table;
Copy
CREATE DYNAMIC TABLE sums
  AS
    SELECT ts_min, sum(c1) FROM intermediate
    GROUP BY 1;
Copy

DISTINCT

Equivalente a GROUP BY ALL sem funções de agregação.

Muitas vezes representa uma oportunidade substancial de otimização.

É uma prática comum aplicar DISTINCT generosamente em todas as consultas para evitar a introdução acidental de duplicatas. Na atualização incremental, as operações DISTINCT consomem recursos de forma recorrente porque duplicatas precisam ser verificadas durante cada atualização.

Ao otimizar o desempenho, encontrar e remover DISTINCTs redundantes pode ser uma vitória fácil. Você pode fazer isso eliminando duplicatas upstream e considerando cuidadosamente as cardinalidades de junção.

<fn> OVER <janela>

Incrementalizado pela recomputação da função de janela para cada chave de partição alterada.

Certifique-se de que há uma cláusula PARTITION BY em sua consulta e os dados de origem são clusterizados por chaves de partição. Certifique-se também de que as alterações incluem uma pequena fração (aproximadamente < 5%) das partições.

<esquerdo> INNER JOIN <direito>

Incrementalizado unindo as alterações do lado esquerdo com as do lado direito e, em seguida, unindo as alterações do lado direito com as do lado esquerdo.

Se um dos lados da junção for pequeno, o desempenho provavelmente será bom. Se um dos lados da junção muda com frequência, clusterizar o outro lado pela chave de junção pode melhorar o desempenho.

<esquerdo> [{LEFT | RIGHT | FULL}] OUTER JOIN <direito>

Incrementalizado ao fatorar em uma operação INNER JOIN e UNION ALL com uma ou duas cláusulas NOT EXISTS para calcular NULLs para não correspondências. Essa consulta fatorada é então incrementalizada.

A junção interna é incrementalizada conforme mostrado. Os inexistentes são incrementalizados verificando se as chaves alteradas de um lado já existiam do outro lado.

Recomendações:

  • Se um dos lados da junção muda com frequência, clusterizar o outro lado pela chave de junção pode melhorar o desempenho.

  • Coloque a tabela que muda com mais frequência no lado esquerdo.

  • Tente minimizar as mudanças no lado oposto ao OUTER. Então para LEFT OUTER, minimize as alterações no lado direito.

  • Para junções FULL, a localidade é muito importante.

LATERAL FLATTEN

Incrementado pela aplicação do operador de nivelamento às linhas alteradas.

Geralmente tem bom desempenho. O custo é escalonado linearmente com o tamanho das mudanças. As mesmas considerações gerais do operador de FROM <tabela base>.