Pular para o conteúdo principal
Cria uma nova view. As views podem ser normais, materializadas, materializadas atualizáveis e de janela.

View normal

Sintaxe:
CREATE [OR REPLACE] VIEW [IF NOT EXISTS] [db.]table_name [(alias1 [, alias2 ...])] [ON CLUSTER cluster_name]
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | INVOKER | NONE }]
AS SELECT ...
[COMMENT 'comment']
Views normais não armazenam dados. Elas apenas leem de outra tabela a cada acesso. Em outras palavras, uma view normal nada mais é do que uma consulta salva. Ao consultar uma view, essa consulta salva é usada como uma subconsulta na cláusula FROM. Como exemplo, suponha que você tenha criado uma view:
CREATE VIEW view AS SELECT ...
e escrever uma consulta:
SELECT a, b, c FROM view
Esta consulta é totalmente equivalente ao uso da subconsulta:
SELECT a, b, c FROM (SELECT ...)

View parametrizada

Views parametrizadas são semelhantes a views normais, mas podem ser criadas com parâmetros que não são resolvidos de imediato. Essas views podem ser usadas com funções de tabela, que especificam o nome da view como nome da função e os valores dos parâmetros como argumentos.
CREATE VIEW view AS SELECT * FROM TABLE WHERE Column1={column1:datatype1} and Column2={column2:datatype2} ...
O comando acima cria uma view para a tabela, que pode ser usada como função de tabela substituindo os parâmetros, como mostrado abaixo.
SELECT * FROM view(column1=value1, column2=value2 ...)

Visão materializada

CREATE MATERIALIZED VIEW [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster_name] [TO[db.]name [(columns)]] [ENGINE = engine] [POPULATE]
[REFRESH ...]
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | NONE }]
AS SELECT ...
[COMMENT 'comment']
CREATE OR REPLACE MATERIALIZED VIEW [db.]table_name [ON CLUSTER cluster_name] [TO[db.]name [(columns)]] [ENGINE = engine] [POPULATE]
[REFRESH ...]
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | NONE }]
AS SELECT ...
[COMMENT 'comment']
OR REPLACE e IF NOT EXISTS são mutuamente excludentes: usá-los em conjunto resulta em erro de sintaxe.

CREATE OR REPLACE MATERIALIZED VIEW

CREATE OR REPLACE MATERIALIZED VIEW substitui atomicamente uma visão materializada existente e sua tabela de armazenamento interna (se houver). A operação requer um motor de banco de dados Atomic ou Replicated.
CREATE OR REPLACE MATERIALIZED VIEW [db.]name [ON CLUSTER cluster]
[TO [db.]target_table]
[ENGINE = engine]
[POPULATE]
[REFRESH ...]
AS SELECT ...
Principais comportamentos:
  • Sem a cláusula TO: a tabela interna antiga é excluída e uma nova é criada. Os dados existentes na tabela interna são perdidos, a menos que POPULATE seja especificado.
  • Com a cláusula TO: apenas a definição da visão é substituída; a tabela de destino e seus dados permanecem inalterados.
  • Compatível com REFRESH, ON CLUSTER e todas as opções de motor. POPULATE é suportado apenas em bancos de dados Atomic — ele é rejeitado em bancos de dados Replicated (veja a observação sobre POPULATE abaixo).
  • Requer os privilégios CREATE VIEW e DROP VIEW.
CREATE OR REPLACE MATERIALIZED VIEW é suportado apenas com os motores de banco de dados Atomic ou Replicated. Não é compatível com o motor de banco de dados Ordinary.
Exemplos:
-- Cria uma visão materializada com uma tabela interna
CREATE OR REPLACE MATERIALIZED VIEW mv
    ENGINE = MergeTree ORDER BY x
    AS SELECT x, sum(y) AS total FROM src GROUP BY x;

-- Substitui por uma nova definição (os dados da tabela interna antiga são perdidos)
CREATE OR REPLACE MATERIALIZED VIEW mv
    ENGINE = MergeTree ORDER BY x
    AS SELECT x, count() AS cnt FROM src GROUP BY x;

-- Substitui com POPULATE para preencher a partir dos dados de origem existentes
CREATE OR REPLACE MATERIALIZED VIEW mv
    ENGINE = MergeTree ORDER BY x
    POPULATE
    AS SELECT x FROM src;

-- Substitui uma visão materializada com tabela interna por uma com cláusula TO (os dados do destino são preservados)
CREATE OR REPLACE MATERIALIZED VIEW mv TO target
    AS SELECT x FROM src;
Aqui está um guia passo a passo sobre como usar visões materializadas.
Visões materializadas armazenam dados transformados pela consulta SELECT correspondente. Ao criar uma visão materializada sem TO [db].[table], você deve especificar ENGINE — o motor de tabela usado para armazenar os dados. Ao criar uma visão materializada com TO [db].[table], você também não pode usar POPULATE. Uma visão materializada é implementada da seguinte forma: ao inserir dados na tabela especificada em SELECT, parte dos dados inseridos é transformada por essa consulta SELECT, e o resultado é inserido na visão.
Visões materializadas no ClickHouse usam nomes de colunas em vez da ordem das colunas durante a inserção na tabela de destino. Se alguns nomes de colunas não estiverem presentes no resultado da consulta SELECT, o ClickHouse usará um valor padrão, mesmo que a coluna não seja Nullable. Uma prática segura é adicionar aliases para cada coluna ao usar visões materializadas.Visões materializadas no ClickHouse são implementadas mais como gatilhos de inserção. Se houver alguma agregação na consulta da visão, ela será aplicada apenas ao lote de dados recém-inseridos. Quaisquer alterações nos dados existentes da tabela de origem (como update, delete, drop partition etc.) não alteram a visão materializada.Visões materializadas no ClickHouse não têm comportamento determinístico em caso de erros. Isso significa que os blocos que já foram gravados serão preservados na tabela de destino, mas todos os blocos após o erro não serão.Por padrão, se o envio para uma das visões falhar, a consulta INSERT também falhará, e alguns blocos podem não ser gravados na tabela de destino. Isso pode ser alterado usando a configuração materialized_views_ignore_errors (você deve defini-la para a consulta INSERT); se você definir materialized_views_ignore_errors=true, quaisquer erros durante o envio para as visões serão ignorados e todos os blocos serão gravados na tabela de destino.Observe também que materialized_views_ignore_errors é definido como true por padrão para tabelas system.*_log.
Se você especificar POPULATE, os dados existentes da tabela serão inseridos na visão ao criá-la, como se fosse executado um CREATE TABLE ... AS SELECT .... Caso contrário, a consulta conterá apenas os dados inseridos na tabela após a criação da visão. Não recomendamos usar POPULATE, pois os dados inseridos na tabela durante a criação da visão não serão inseridos nela.
Como POPULATE funciona como CREATE TABLE ... AS SELECT ..., ele tem algumas limitações:
  • Não é compatível com banco de dados Replicated
  • Não é compatível com ClickHouse Cloud
Em vez disso, pode-se usar um INSERT ... SELECT separado.
Uma consulta SELECT pode conter DISTINCT, GROUP BY, ORDER BY, LIMIT. Observe que as transformações correspondentes são realizadas de forma independente em cada bloco de dados inseridos. Por exemplo, se GROUP BY estiver definido, os dados serão agregados durante a inserção, mas apenas dentro de um único pacote de dados inseridos. Os dados não serão agregados posteriormente. A exceção é ao usar um ENGINE que realiza agregação de dados por conta própria, como SummingMergeTree. Se a visão materializada usar a construção TO [db.]name, você pode fazer DETACH da visão, executar ALTER na tabela de destino e, em seguida, fazer ATTACH da visão previamente desanexada (DETACH). Observe que a visão materializada é influenciada pela configuração optimize_on_insert. Os dados são mesclados antes de serem inseridos na visão. As views têm a mesma aparência das tabelas normais. Por exemplo, elas são listadas no resultado da consulta SHOW TABLES. Para excluir uma view, use DROP VIEW. Embora DROP TABLE também funcione para VIEWs.

Segurança SQL

DEFINER e SQL SECURITY permitem especificar qual usuário do ClickHouse deve ser usado ao executar a consulta subjacente da visão. SQL SECURITY tem três valores válidos: DEFINER, INVOKER ou NONE. Você pode especificar qualquer usuário existente ou CURRENT_USER na cláusula DEFINER. A tabela a seguir mostra quais permissões são necessárias para cada usuário ao consultar uma visão. Observe que, independentemente da opção de segurança SQL, em todos os casos ainda é necessário ter GRANT SELECT ON <view> para poder lê-la.
Opção de segurança SQLVisãoVisão materializada
DEFINER alicealice deve ter o privilégio SELECT na tabela de origem da visão.alice deve ter o privilégio SELECT na tabela de origem da visão e o privilégio INSERT na tabela de destino da visão.
INVOKERO usuário deve ter o privilégio SELECT na tabela de origem da visão.SQL SECURITY INVOKER não pode ser especificado para visões materializadas.
NONE--
SQL SECURITY NONE é uma opção obsoleta. Qualquer usuário com permissões para criar visões com SQL SECURITY NONE poderá executar qualquer consulta arbitrária. Portanto, é necessário ter GRANT ALLOW SQL SECURITY NONE TO <user> para criar uma visão com essa opção.
Se DEFINER/SQL SECURITY não forem especificados, os valores padrão serão usados: Se uma visão for anexada sem DEFINER/SQL SECURITY especificados, o valor padrão será SQL SECURITY NONE para a visão materializada e SQL SECURITY INVOKER para a view normal. Para alterar a segurança SQL de uma visão existente, use
ALTER TABLE MODIFY SQL SECURITY { DEFINER | INVOKER | NONE } [DEFINER = { user | CURRENT_USER }]

Exemplos

CREATE VIEW test_view
DEFINER = alice SQL SECURITY DEFINER
AS SELECT ...
CREATE VIEW test_view
SQL SECURITY INVOKER
AS SELECT ...

Visualização em tempo real

Este recurso está obsoleto e será removido no futuro. Para sua conveniência, a documentação antiga está disponível aqui

visão materializada atualizável

CREATE MATERIALIZED VIEW [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
REFRESH EVERY|AFTER interval [OFFSET interval]
[RANDOMIZE FOR interval]
[DEPENDS ON [db.]name [, [db.]name [, ...]]]
[SETTINGS name = value [, name = value [, ...]]]
[APPEND]
[TO[db.]name] [(columns)] [ENGINE = engine]
[EMPTY]
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | NONE }]
AS SELECT ...
[COMMENT 'comment']
em que interval é uma sequência de intervalos simples:
number SECOND|MINUTE|HOUR|DAY|WEEK|MONTH|YEAR
Executa periodicamente a consulta correspondente e armazena o resultado em uma tabela.
  • Se APPEND for especificado, cada atualização insere linhas na tabela sem excluir as já existentes. A inserção não é atômica, assim como em uma consulta INSERT INTO ... SELECT comum.
  • Caso contrário, cada atualização substitui atomicamente o conteúdo anterior da tabela.
Diferenças em relação às visões materializadas comuns, não atualizáveis:
  • Não há gatilho de inserção. Quando novos dados são inseridos na tabela especificada em SELECT, eles não são enviados automaticamente para a visão materializada atualizável. Em vez disso, a inserção de dados ocorre apenas durante execuções de atualização periódicas ou manuais.
  • Não há restrições para a consulta SELECT. Funções de tabela (por exemplo, url()), views, UNION e JOIN são permitidos.
As configurações na parte REFRESH ... SETTINGS da consulta são configurações de atualização (por exemplo, refresh_retries), distintas das configurações comuns (por exemplo, max_threads). As configurações comuns podem ser especificadas com SETTINGS no final da consulta.

Programação de atualização

Exemplos de programação de atualização:
REFRESH EVERY 1 DAY -- todo dia, à meia-noite (UTC)
REFRESH EVERY 1 MONTH -- no 1º dia de cada mês, à meia-noite
REFRESH EVERY 1 MONTH OFFSET 5 DAY 2 HOUR -- no 6º dia de cada mês, às 2:00
REFRESH EVERY 2 WEEK OFFSET 5 DAY 15 HOUR 10 MINUTE -- a cada dois sábados, às 15:10
REFRESH EVERY 30 MINUTE -- às 00:00, 00:30, 01:00, 01:30, etc
REFRESH AFTER 30 MINUTE -- 30 minutos após a conclusão do refresh anterior, sem alinhamento com o horário do dia
-- REFRESH AFTER 1 HOUR OFFSET 1 MINUTE -- erro de sintaxe, OFFSET não é permitido com AFTER
REFRESH EVERY 1 WEEK 2 DAYS -- a cada 9 dias, sem dia fixo da semana ou do mês;
                            -- especificamente, quando o número do dia (desde 1969-12-29) é divisível por 9
REFRESH EVERY 5 MONTHS -- a cada 5 meses, em meses diferentes a cada ano (pois 12 não é divisível por 5);
                       -- especificamente, quando o número do mês (desde 1970-01) é divisível por 5
RANDOMIZE FOR ajusta aleatoriamente o momento de cada atualização, por exemplo:
REFRESH EVERY 1 DAY OFFSET 2 HOUR RANDOMIZE FOR 1 HOUR -- todos os dias em um horário aleatório entre 01:30 e 02:30
No máximo, uma atualização pode estar em execução por vez para uma determinada visão. Por exemplo, se uma visão com REFRESH EVERY 1 MINUTE levar 2 minutos para ser atualizada, ela simplesmente passará a ser atualizada a cada 2 minutos. Se depois ficar mais rápida e passar a ser atualizada em 10 segundos, voltará a ser atualizada a cada minuto. (Em particular, ela não será atualizada a cada 10 segundos para compensar um acúmulo de atualizações perdidas — esse acúmulo não existe.) Além disso, uma atualização é iniciada imediatamente após a criação da visão materializada, a menos que EMPTY seja especificado na consulta CREATE. Se EMPTY for especificado, a primeira atualização ocorrerá de acordo com o agendamento.

Em banco de dados Replicated

Se a visão materializada atualizável estiver em um banco de dados Replicated, as réplicas se coordenam entre si para que apenas uma delas execute a atualização em cada horário agendado. O motor de tabela ReplicatedMergeTree é necessário para que todas as réplicas vejam os dados produzidos pela atualização. No modo APPEND, a coordenação pode ser desativada com SETTINGS all_replicas = 1. Isso faz com que as réplicas executem as atualizações de forma independente. Nesse caso, o ReplicatedMergeTree não é necessário. No modo sem APPEND, apenas a atualização coordenada é compatível. Para atualização não coordenada, use o banco de dados Atomic e a consulta CREATE ... ON CLUSTER para criar visões materializadas atualizáveis em todas as réplicas. A coordenação é feita por meio do Keeper. O caminho do znode é determinado pela configuração do servidor default_replica_path.

Dependências de atualização

DEPENDS ON sincroniza as atualizações de diferentes tabelas. Por exemplo, suponha que haja uma cadeia de duas visões materializadas atualizáveis:
CREATE MATERIALIZED VIEW source REFRESH EVERY 1 DAY AS SELECT * FROM url(...)
CREATE MATERIALIZED VIEW destination REFRESH EVERY 1 DAY AS SELECT ... FROM source
Sem DEPENDS ON, ambas as views iniciarão a atualização à meia-noite, e destination normalmente verá em source os dados de ontem. Se adicionarmos uma dependência:
CREATE MATERIALIZED VIEW destination REFRESH EVERY 1 DAY DEPENDS ON source AS SELECT ... FROM source
então a atualização de destination só começará depois que a atualização de source terminar nesse dia, de modo que destination se baseie em dados atualizados. Como alternativa, o mesmo resultado pode ser obtido com:
CREATE MATERIALIZED VIEW destination REFRESH AFTER 1 HOUR DEPENDS ON source AS SELECT ... FROM source
em que 1 HOUR pode ser qualquer duração menor que o período de refresh de source. A tabela dependente não será atualizada com mais frequência do que qualquer uma de suas dependências. Essa é uma forma válida de configurar uma cadeia de views atualizáveis sem especificar o período real de refresh mais de uma vez. Mais alguns exemplos:
  • REFRESH EVERY 1 DAY OFFSET 10 MINUTE (destination) depende de REFRESH EVERY 1 DAY (source)
    Se o refresh de source levar mais de 10 minutos, destination esperará por ele.
  • REFRESH EVERY 1 DAY OFFSET 1 HOUR depende de REFRESH EVERY 1 DAY OFFSET 23 HOUR
    Semelhante ao caso acima, mesmo que os refreshes correspondentes ocorram em dias diferentes do calendário. O refresh de destination no dia X+1 esperará pelo refresh de source no dia X (se ele levar mais de 2 horas).
  • REFRESH EVERY 2 HOUR depende de REFRESH EVERY 1 HOUR
    O refresh de 2 HOUR ocorre após o refresh de 1 HOUR a cada duas horas, por exemplo, após o refresh da meia-noite, depois após o refresh das 2h etc.
  • REFRESH EVERY 1 MINUTE depende de REFRESH EVERY 2 HOUR
    destination é atualizada uma vez após cada refresh de source, ou seja, a cada 2 horas. O 1 MINUTE é efetivamente ignorado.
  • REFRESH AFTER 1 HOUR depende de REFRESH AFTER 1 HOUR
    Atualmente, isso não é recomendado.
DEPENDS ON só funciona entre visões materializadas atualizáveis. Listar uma tabela comum na lista DEPENDS ON impedirá que a view seja atualizada (as dependências podem ser removidas com ALTER; consulte Alterando os parâmetros de atualização).

Configurações de atualização

Configurações de atualização disponíveis:
  • refresh_retries - Quantas vezes tentar novamente se a consulta de atualização falhar com uma exceção. Se todas as tentativas falharem, a atualização será adiada para o próximo horário agendado. 0 significa nenhuma tentativa adicional; -1 significa tentativas infinitas. Padrão: 2.
  • refresh_retry_initial_backoff_ms - Atraso antes da primeira tentativa de repetição, se refresh_retries não for zero. Cada nova tentativa dobra esse atraso, até refresh_retry_max_backoff_ms. Padrão: 100 ms.
  • refresh_retry_max_backoff_ms - Limite para o crescimento exponencial do atraso entre tentativas de atualização. Padrão: 60000 ms (1 minuto).
  • all_replicas - Em um banco de dados Replicated com APPEND, controla se todas as réplicas são atualizadas de forma independente ou se apenas uma réplica é atualizada em cada horário agendado. Não pode ser alterado após a criação da view. Padrão: false.
  • prefer_dependency_replica - Quando a view tem DEPENDS ON, a réplica que executou a atualização pai recebe prioridade para executar a atualização dependente; as outras réplicas adiam sua tentativa em prefer_dependency_replica_delay_ms. Útil com SharedMergeTree para evitar que o atraso de replicação cause ausência de dados em cadeias de atualizações dependentes. Padrão: false.
  • prefer_dependency_replica_delay_ms - Por quanto tempo réplicas não preferenciais aguardam antes de tentar executar uma atualização dependente quando prefer_dependency_replica está habilitado. Padrão: 2000 ms.

Alterando os parâmetros de atualização

Os parâmetros de atualização de uma visão materializada atualizável existente podem ser alterados com ALTER TABLE ... MODIFY REFRESH:
ALTER TABLE [db.]name MODIFY REFRESH EVERY|AFTER ... [RANDOMIZE FOR ...] [DEPENDS ON ...] [SETTINGS ...]
O agendamento (EVERY ou AFTER) é obrigatório: a instrução sempre substitui todos os parâmetros de atualização — agendamento, RANDOMIZE FOR, DEPENDS ON e configurações de atualização — pelos valores especificados. Tudo o que for omitido é redefinido para o valor padrão (configurações) ou removido (dependências, aleatorização).
  • Para alterar apenas as configurações de atualização (por exemplo, refresh_retries), repita o agendamento atual:
    ALTER TABLE rmv MODIFY REFRESH EVERY 1 HOUR SETTINGS refresh_retries = 5;
    
  • ALTER TABLE ... MODIFY SETTING refresh_retries = ... não tem suporte em visões materializadas; é preciso usar MODIFY REFRESH.
  • Não há suporte para adicionar ou remover APPEND.
  • A configuração all_replicas não pode ser alterada após a criação.
Exemplos:
-- Alterar o agendamento, removendo as configurações e dependências existentes.
ALTER TABLE rmv MODIFY REFRESH EVERY 30 MINUTE;

-- Alterar o agendamento e ajustar o comportamento de retentativas.
ALTER TABLE rmv MODIFY REFRESH EVERY 30 MINUTE
SETTINGS refresh_retries = 5,
         refresh_retry_initial_backoff_ms = 500,
         refresh_retry_max_backoff_ms = 60000;

-- Manter a dependência ao alterar o período.
ALTER TABLE rmv MODIFY REFRESH EVERY 6 HOUR DEPENDS ON other_rmv;

-- Remover a dependência omitindo `DEPENDS ON`.
ALTER TABLE rmv MODIFY REFRESH EVERY 6 HOUR;

Outras operações

O status de todas as visões materializadas atualizáveis está disponível na tabela system.view_refreshes. Ela contém, em particular, o progresso da atualização (se estiver em execução), os horários da última e da próxima atualização e a mensagem de exceção caso uma atualização falhe. Para interromper, iniciar, disparar ou cancelar atualizações manualmente, use SYSTEM STOP|START|REFRESH|WAIT|CANCEL VIEW. Para aguardar a conclusão de uma atualização, use SYSTEM WAIT VIEW. Isso é útil, em particular, para aguardar a atualização inicial após criar uma view.
Curiosidade: a consulta de atualização pode ler da view que está sendo atualizada, visualizando a versão dos dados anterior à atualização. Isso significa que você pode implementar o jogo da vida de Conway: https://pastila.nl/?00021a4b/d6156ff819c83d490ad2dcec05676865#O0LGWTO7maUQIA4AcGUtlA==

Window View

Este é um recurso experimental que pode mudar de forma incompatível com versões anteriores em versões futuras. Ative o uso de window views e da consulta WATCH com a configuração allow_experimental_window_view. Digite o comando set allow_experimental_window_view = 1.
CREATE WINDOW VIEW [IF NOT EXISTS] [db.]table_name [TO [db.]table_name] [INNER ENGINE engine] [ENGINE engine] [WATERMARK strategy] [ALLOWED_LATENESS interval_function] [POPULATE]
AS SELECT ...
GROUP BY time_window_function
[COMMENT 'comment']
Uma window view pode agregar dados por janela de tempo e gerar os resultados quando a janela estiver pronta para disparar. Ela armazena os resultados parciais da agregação em uma tabela interna (ou especificada) para reduzir a latência e pode enviar o resultado do processamento para uma tabela especificada ou enviar notificações usando a consulta WATCH. Criar uma window view é semelhante a criar uma MATERIALIZED VIEW. A window view precisa de um mecanismo de armazenamento interno para armazenar dados intermediários. O armazenamento interno pode ser especificado usando a cláusula INNER ENGINE; a window view usará AggregatingMergeTree como mecanismo interno padrão. Ao criar uma window view sem TO [db].[table], você deve especificar ENGINE — o motor de tabela para armazenar dados.

Funções de janela de tempo

As funções de janela de tempo são usadas para obter os limites inferior e superior da janela dos registros. A Window View precisa ser usada com uma função de janela de tempo.

ATRIBUTOS DE TEMPO

A window view oferece suporte a tempo de processamento e tempo de evento. O tempo de processamento permite que a window view produza resultados com base no horário da máquina local e é usado por padrão. É a noção de tempo mais simples, mas não fornece determinismo. O atributo de tempo de processamento pode ser definido configurando o time_attr da função de janela temporal como uma coluna da tabela ou usando a função now(). A consulta a seguir cria uma window view com tempo de processamento.
CREATE WINDOW VIEW wv AS SELECT count(number), tumbleStart(w_id) as w_start from date GROUP BY tumble(now(), INTERVAL '5' SECOND) as w_id
Tempo do evento é o momento em que cada evento individual ocorreu no dispositivo que o gerou. Esse tempo normalmente é incorporado aos registros quando o evento é gerado. O processamento por tempo do evento permite resultados consistentes mesmo em casos de eventos fora de ordem ou tardios. A window view oferece suporte ao processamento por tempo do evento usando a sintaxe WATERMARK. A window view fornece três estratégias de watermark:
  • STRICTLY_ASCENDING: Emite um watermark com o timestamp máximo observado até o momento. Linhas com timestamp menor que o timestamp máximo não são consideradas tardias.
  • ASCENDING: Emite um watermark com o timestamp máximo observado até o momento menos 1. Linhas com timestamp igual ou menor que o timestamp máximo não são consideradas tardias.
  • BOUNDED: WATERMARK=INTERVAL. Emite watermarks, que correspondem ao timestamp máximo observado menos o atraso especificado.
As consultas a seguir são exemplos de criação de uma window view com WATERMARK:
CREATE WINDOW VIEW wv WATERMARK=STRICTLY_ASCENDING AS SELECT count(number) FROM date GROUP BY tumble(timestamp, INTERVAL '5' SECOND);
CREATE WINDOW VIEW wv WATERMARK=ASCENDING AS SELECT count(number) FROM date GROUP BY tumble(timestamp, INTERVAL '5' SECOND);
CREATE WINDOW VIEW wv WATERMARK=INTERVAL '3' SECOND AS SELECT count(number) FROM date GROUP BY tumble(timestamp, INTERVAL '5' SECOND);
Por padrão, a janela será acionada quando o watermark chegar, e os elementos que chegarem atrasados em relação ao watermark serão descartados. A window view oferece suporte ao processamento de eventos tardios definindo ALLOWED_LATENESS=INTERVAL. Um exemplo de tratamento de atraso é:
CREATE WINDOW VIEW test.wv TO test.dst WATERMARK=ASCENDING ALLOWED_LATENESS=INTERVAL '2' SECOND AS SELECT count(a) AS count, tumbleEnd(wid) AS w_end FROM test.mt GROUP BY tumble(timestamp, INTERVAL '5' SECOND) AS wid;
Observe que os elementos emitidos por um acionamento tardio devem ser tratados como resultados atualizados de uma computação anterior. Em vez de acionar no fim das janelas, a window view acionará imediatamente quando o evento tardio chegar. Assim, isso resultará em várias saídas para a mesma janela. Os usuários precisam levar esses resultados duplicados em consideração ou deduplicá-los. Você pode modificar a consulta SELECT especificada na window view usando a instrução ALTER TABLE ... MODIFY QUERY. A estrutura de dados resultante da nova consulta SELECT deve ser a mesma da consulta SELECT original, com ou sem a cláusula TO [db.]name. Observe que os dados na janela atual serão perdidos, porque o estado intermediário não pode ser reutilizado.

Monitorando novas janelas

A window view oferece suporte à consulta WATCH para acompanhar alterações, ou você pode usar a sintaxe TO para enviar os resultados para uma tabela.
WATCH [db.]window_view
[EVENTS]
[LIMIT n]
[FORMAT format]
É possível especificar um LIMIT para definir o número de atualizações a serem recebidas antes de encerrar a consulta. A cláusula EVENTS pode ser usada para obter uma forma abreviada da consulta WATCH, na qual, em vez do resultado da consulta, você receberá apenas o watermark mais recente da consulta.

Configurações

  • window_view_clean_interval: O intervalo de limpeza da window view, em segundos, para liberar dados obsoletos. O sistema manterá as janelas que ainda não tiverem sido totalmente acionadas, de acordo com o tempo do sistema ou com a configuração de WATERMARK, e os demais dados serão excluídos.
  • window_view_heartbeat_interval: O intervalo de heartbeat, em segundos, para indicar que a consulta watch está ativa.
  • wait_for_window_view_fire_signal_timeout: Tempo limite de espera pelo sinal de acionamento da window view no processamento de tempo de evento.

Exemplo

Suponha que precisemos contar o número de logs de cliques a cada 10 segundos em uma tabela de logs chamada data, e que a estrutura da tabela seja:
CREATE TABLE data ( `id` UInt64, `timestamp` DateTime) ENGINE = Memory;
Primeiro, criamos uma window view com uma tumble window de 10 segundos:
CREATE WINDOW VIEW wv as select count(id), tumbleStart(w_id) as window_start from data group by tumble(timestamp, INTERVAL '10' SECOND) as w_id
Em seguida, usamos a consulta WATCH para obter os resultados.
WATCH wv
Quando os logs são inseridos na tabela data,
INSERT INTO data VALUES(1,now())
A consulta WATCH deve exibir os resultados da seguinte forma:
┌─count(id)─┬────────window_start─┐
│         1 │ 2020-01-14 16:56:40 │
└───────────┴─────────────────────┘
Como alternativa, podemos direcionar a saída para outra tabela usando a sintaxe TO.
CREATE WINDOW VIEW wv TO dst AS SELECT count(id), tumbleStart(w_id) as window_start FROM data GROUP BY tumble(timestamp, INTERVAL '10' SECOND) as w_id
Exemplos adicionais podem ser encontrados entre os testes stateful do ClickHouse (lá, eles se chamam *window_view*).

Uso de Window View

A window view é útil nos seguintes cenários:
  • Monitoramento: Agrega e calcula métricas a partir dos logs ao longo do tempo e envia os resultados para uma tabela de destino. O dashboard pode usar a tabela de destino como tabela de origem.
  • Análise: Agrega e pré-processa automaticamente os dados em uma janela de tempo. Isso pode ser útil ao analisar um grande volume de logs. O pré-processamento elimina cálculos repetidos em várias consultas e reduz a latência das consultas.

Views temporárias

O ClickHouse oferece suporte a views temporárias com as seguintes características (correspondentes às tabelas temporárias, quando aplicável):
  • Duração da sessão Uma view temporária existe apenas durante a sessão atual. Ela é removida automaticamente quando a sessão termina.
  • Sem banco de dados Você não pode qualificar uma view temporária com o nome de um banco de dados. Ela existe fora dos bancos de dados (espaço de nomes da sessão).
  • Não replicado / sem ON CLUSTER Objetos temporários são locais à sessão e não podem ser criados com ON CLUSTER.
  • Resolução de nomes Se um objeto temporário (tabela ou view) tiver o mesmo nome de um objeto persistente e uma consulta referenciar esse nome sem um banco de dados, o objeto temporário será usado.
  • Objeto lógico (sem armazenamento) Uma view temporária armazena apenas o texto do seu SELECT (usa internamente o armazenamento View). Ela não persiste dados e não aceita INSERT.
  • Cláusula de engine Você não precisa especificar ENGINE; se ele for informado como ENGINE = View, será ignorado/tratado como a mesma view lógica.
  • Segurança / privilégios Criar uma view temporária exige o privilégio CREATE TEMPORARY VIEW, que é concedido implicitamente por CREATE VIEW.
  • SHOW CREATE Use SHOW CREATE TEMPORARY VIEW view_name; para exibir o DDL de uma view temporária.

Sintaxe

CREATE TEMPORARY VIEW [IF NOT EXISTS] view_name AS <select_query>
OR REPLACE não tem suporte para views temporárias (para manter a consistência com as tabelas temporárias). Se você precisar “substituir” uma view temporária, exclua-a e crie-a novamente.

Exemplos

Crie uma tabela-fonte temporária e uma view temporária sobre ela:
CREATE TEMPORARY TABLE t_src (id UInt32, val String);
INSERT INTO t_src VALUES (1, 'a'), (2, 'b');

CREATE TEMPORARY VIEW tview AS
SELECT id, upper(val) AS u
FROM t_src
WHERE id <= 2;

SELECT * FROM tview ORDER BY id;
Exiba a DDL:
SHOW CREATE TEMPORARY VIEW tview;
Removê-la:
DROP TEMPORARY VIEW IF EXISTS tview;  -- views temporárias são removidas com a sintaxe TEMPORARY TABLE

Não permitidos / limitações

  • CREATE OR REPLACE TEMPORARY VIEW ...não permitido (use DROP + CREATE).
  • CREATE TEMPORARY MATERIALIZED VIEW ... / WINDOW VIEWnão permitido.
  • CREATE TEMPORARY VIEW db.view AS ...não permitido (sem qualificador de banco de dados).
  • CREATE TEMPORARY VIEW view ON CLUSTER 'name' AS ...não permitido (objetos temporários são locais da sessão).
  • POPULATE, REFRESH, TO [db.table], motores internos e todas as cláusulas específicas de MV → não se aplicam a visões temporárias.

Notas sobre consultas distribuídas

Uma view temporária é apenas uma definição; não há dados para transferir. Se sua view temporária fizer referência a tabelas temporárias (por exemplo, Memory), os dados delas podem ser enviados a servidores remotos durante a execução de consultas distribuídas, da mesma forma que acontece com as tabelas temporárias.

Exemplo

-- Uma tabela em memória com escopo de sessão
CREATE TEMPORARY TABLE temp_ids (id UInt64) ENGINE = Memory;

INSERT INTO temp_ids VALUES (1), (5), (42);

-- Uma view com escopo de sessão sobre a tabela temporária (puramente lógica)
CREATE TEMPORARY VIEW v_ids AS
SELECT id FROM temp_ids;

-- Substitua 'test' pelo nome do seu cluster.
-- O GLOBAL JOIN força o ClickHouse a *enviar* o lado menor do join (temp_ids via v_ids)
-- para cada servidor remoto que executa o lado esquerdo.
SELECT count()
FROM cluster('test', system.numbers) AS n
GLOBAL ANY INNER JOIN v_ids USING (id)
WHERE n.number < 100;

Última modificação em 10 de junho de 2026