Uso de restrições de imutabilidade em tabelas dinâmicas

As restrições de imutabilidade oferecem mais controle sobre como e quando suas tabelas dinâmicas são atualizadas. As restrições permitem que partes da tabela permaneçam estáticas, em vez de toda a tabela refletir os resultados da consulta mais recente.

Ao marcar partes específicas de uma tabela dinâmica como imutáveis, você pode executar as seguintes tarefas:

  • Impedir a propagação de atualizações ou exclusões em dados existentes.

  • Restringir inserções, atualizações e exclusões para linhas que atendam a uma condição.

  • Limitar modificações futuras sem deixar de permitir atualizações incrementais em outras partes da tabela.

  • Preencher tabelas dinâmicas com restrições de imutabilidade. Para obter mais informações, consulte Criação de tabelas dinâmicas usando preenchimento.

O restante da tabela, ou seja, as linhas que não correspondem à condição de imutabilidade, permanece mutável e pode ser atualizado.

Para impor restrições de imutabilidade, especifique o parâmetro IMMUTABLE WHERE o quando você executar o comando CREATE DYNAMIC TABLE ou ALTER DYNAMIC TABLE. Colunas referenciadas na condição IMMUTABLE WHERE devem ser colunas da tabela dinâmica, não da tabela base. Por exemplo, a expressão IMMUTABLE WHERE na seguinte instrução SQL pode usar apenas id1, e não id:

CREATE DYNAMIC TABLE my_dynamic_table (id1 INT)
  TARGET_LAG = '20 minutes'
  WAREHOUSE = mywh
  IMMUTABLE WHERE ( <expr> )
  AS
    SELECT id AS id1 FROM staging_table;
Copy

Para ver se uma linha é ou não imutável, use a coluna METADATA$IS_IMMUTABLE. Por exemplo, SELECT * , METADATA$IS_IMMUTABLE FROM my_dynamic_table.

Para visualizar as restrições de imutabilidade em suas tabelas dinâmicas, execute o comando SHOW DYNAMIC TABLES. A coluna immutable_where mostra a restrição IMMUTABLE WHERE definida na tabela ou NULL se nenhuma estiver definida.

Para informações sobre custos de computação, consulte Calcular o custo de restrições de imutabilidade.

Exemplo: Uso de IMMUTABLE WHERE para impedir a recomputação de dados antigos se uma tabela de dimensões mudar

No exemplo a seguir, a atualização de uma linha na tabela de dimensões faz com que sejam reprocessados os fatos do último dia, em vez de todos os fatos históricos:

CREATE DYNAMIC TABLE joined_data
  TARGET_LAG = '1 minute'
  WAREHOUSE = mywh
  IMMUTABLE WHERE (timestamp_col < CURRENT_TIMESTAMP() - INTERVAL '1 day')
  AS
    SELECT F.primary_key primary_key, F.timestamp_col timestamp_col, D.value dim_value
    FROM fact_table F
    LEFT OUTER JOIN dimension_table D USING (primary_key);
Copy

Exemplo: Tabela dinâmica de retenção ilimitada e tabela base de retenção limitada

O exemplo a seguir cria uma tabela de preparação com uma janela limitada de dados adicionados recentemente e uma tabela dinâmica que armazena todos os dados analisados e filtrados:

CREATE TABLE staging_data (raw TEXT, ts TIMESTAMP);

CREATE DYNAMIC TABLE parsed_data
  TARGET_LAG = '1 minute'
  WAREHOUSE = mywh
  IMMUTABLE WHERE (ts < CURRENT_TIMESTAMP() - INTERVAL '7 days')
  AS
    SELECT parse_json(raw):event_id::string event_id, parse_json(raw):name::string name, parse_json(raw):region::string region, ts
    FROM staging_data WHERE region = 'US';

-- Delete old staging data using Task
CREATE TASK delete_old_staging_data
  WAREHOUSE = mywh
  SCHEDULE = '24 hours'
  AS
    DELETE FROM staging_data WHERE ts < CURRENT_TIMESTAMP() - INTERVAL '30 days';
Copy

Exemplo: uso de IMMUTABLE WHERE para habilitar atualizações incrementais downstream quando a tabela dinâmica upstream é executada no modo de atualização completa

Algumas construções de consulta, como funções de tabela definidas pelo usuário (User-Defined Table Functions, UDTFs) em Python, exigem uma tabela dinâmica para execução no modo de atualização completa. Normalmente, essa limitação impede o processamento incremental. Para permitir que as tabelas downstream permaneçam incrementais, você pode definir uma região imutável usando a cláusula IMMUTABLE WHERE, conforme mostrado no exemplo a seguir. Dessa forma, as tabelas downstream ainda se beneficiam das otimizações de desempenho, mesmo quando a tabela upstream requer atualizações completas.

CREATE FUNCTION my_udtf(x varchar)
  RETURNS TABLE (output VARCHAR)
  LANGUAGE PYTHON
  AS $$ ... $$;

CREATE DYNAMIC TABLE udtf_dt
  TARGET_LAG = '1 hour'
  WAREHOUSE = mywh
  REFRESH_MODE = FULL
  IMMUTABLE WHERE (ts < current_timestamp() - interval '1 day')
  AS
    SELECT ts, data, output, join_key FROM input_table, TABLE(my_udtf(data));

CREATE DYNAMIC TABLE incremental_join_dt
  TARGET_LAG = '1 hour'
  WAREHOUSE = mywh
  REFRESH_MODE = INCREMENTAL
  IMMUTABLE WHERE (ts < current_timestamp() - interval '1 day')
  AS
    SELECT * FROM udtf_dt JOIN dim_table USING (join_key);
Copy

Limitações e considerações ao definir restrições de imutabilidade

  • O predicado IMMUTABLE WHERE é ignorado durante a atualização inicial, mas se aplica a todas as atualizações subsequentes. No modo de atualização completa, o predicado limita a nova computação apenas às linhas que não correspondem à condição.

  • Fluxos e tabelas dinâmicas de atualização incremental podem ler tabelas dinâmicas de atualização completas que têm restrições de imutabilidade.

  • As restrições IMMUTABLE WHERE são copiadas durante a clonagem e a replicação sem limitações.

  • Todas as limitações das tabelas dinâmicas regulares ainda se aplicam. Além disso, as seguintes limitações são aplicadas:

    • Só pode haver um único predicado IMMUTABLE WHERE em uma tabela dinâmica. A definição de outro predicado com um comando ALTER DYNAMIC TABLE … SET IMMUTABLE WHERE substitui um predicado existente.

    • As restrições IMMUTABLE WHERE não podem conter os seguintes itens:

      • Subconsultas.

      • Funções não determinísticas, exceto para funções de carimbo de data/hora, como CURRENT_TIMESTAMP() ou CURRENT_DATE(). Se você usar funções de carimbo de data/hora, deverá usá-las para que a região imutável não diminua com o tempo. Por exemplo, TIMESTAMP_COL < CURRENT_TIMESTAMP() is allowed but TIMESTAMP_COL > CURRENT_TIMESTAMP() não faz isso.

      • Funções definidas pelo usuário e externas.

      • Colunas de metadados; por exemplo, aquelas que começam com METADATA$.

      • Colunas que são o resultado de agregados, funções de janela ou não determinísticas, ou colunas que são passadas por um operador de função de janela. Nas tabelas dinâmicas a seguir, somente col3 pode ser usado em predicados IMMUTABLE WHERE:

        CREATE DYNAMIC TABLE aggregates TARGET_LAG = '1 minute' WAREHOUSE = mywh
          AS SELECT col3, SUM(col2) AS col2 FROM input_table
          GROUP BY col3;
        
        CREATE DYNAMIC TABLE window_fns TARGET_LAG = '1 minute' WAREHOUSE = mywh
          AS SELECT col3, SUM(col4) OVER (PARTITION BY col3 ORDER BY col4) AS col2, col5 FROM input_table;
        
        Copy
    • Você só pode definir uma única condição IMMUTABLE WHERE em uma tabela dinâmica. Para substituir um predicado existente, use o comando ALTER DYNAMIC TABLE, como mostrado no exemplo a seguir:

      -- Set or replace an existing predicate:
      ALTER DYNAMIC TABLE my_dynamic_table SET IMMUTABLE WHERE ( <expr> );
      
      Copy
      -- Remove an existing predicate:
      ALTER DYNAMIC TABLE my_dynamic_table UNSET IMMUTABLE WHERE;
      
      Copy