Skip to main content
Este motor:
  • Permite gravar rapidamente estados de objetos que mudam continuamente.
  • Exclui estados antigos de objetos em segundo plano. Isso reduz significativamente o volume de armazenamento.
Consulte a seção colapsamento para mais detalhes. O motor herda de MergeTree e adiciona a lógica de colapsamento de linhas ao algoritmo de mesclagem de partes de dados. VersionedCollapsingMergeTree tem a mesma finalidade que CollapsingMergeTree, mas usa um algoritmo de colapsamento diferente que permite inserir dados em qualquer ordem com várias threads. Em particular, a coluna Version ajuda a colapsar as linhas corretamente, mesmo que sejam inseridas fora de ordem. Em contraste, CollapsingMergeTree permite apenas inserção estritamente consecutiva.

Criando uma tabela

Para obter uma descrição dos parâmetros de consulta, consulte a descrição da consulta.

Parâmetros do motor

Cláusulas da consulta

Ao criar uma tabela VersionedCollapsingMergeTree, são necessárias as mesmas cláusulas exigidas na criação de uma tabela MergeTree.

colapsamento

Dados

Considere uma situação em que você precisa salvar dados que mudam continuamente de um objeto. É natural ter uma linha para um objeto e atualizar essa linha sempre que houver alterações. No entanto, a operação de atualização é cara e lenta para um SGBD, porque exige reescrever os dados no armazenamento. A atualização não é aceitável se você precisa gravar dados rapidamente, mas pode gravar as alterações de um objeto de forma sequencial, como a seguir. Use a coluna Sign ao gravar a linha. Se Sign = 1, isso significa que a linha representa um estado de um objeto (vamos chamá-la de linha de “estado”). Se Sign = -1, isso indica o cancelamento do estado de um objeto com os mesmos atributos (vamos chamá-la de linha de “cancelamento”). Use também a coluna Version, que deve identificar cada estado de um objeto com um número distinto. Por exemplo, queremos calcular quantas páginas os usuários visitaram em um site e por quanto tempo permaneceram nele. Em determinado momento, gravamos a seguinte linha com o estado da atividade do usuário:
Em algum momento depois, registramos a alteração na atividade do usuário nas duas linhas a seguir.
A primeira linha cancela o estado anterior do objeto (usuário). Ela deve copiar todos os campos do estado cancelado, exceto Sign. A segunda linha contém o estado atual. Como precisamos apenas do último estado da atividade do usuário, as linhas
pode ser excluída, colapsando o estado inválido (antigo) do objeto. VersionedCollapsingMergeTree faz isso durante a mesclagem das partes de dados. Para descobrir por que precisamos de duas linhas para cada alteração, consulte Algorithm. Observações sobre o uso
  1. O programa que grava os dados deve manter o estado de um objeto na memória para poder cancelá-lo. A string “Cancel” deve conter cópias dos campos da chave primária, da versão da string “state” e o Sign oposto. Isso aumenta o tamanho inicial do armazenamento, mas permite gravar os dados rapidamente.
  2. Arrays longos e crescentes em colunas reduzem a eficiência do motor devido à carga de gravação. Quanto mais simples forem os dados, maior será a eficiência.
  3. Os resultados de SELECT dependem fortemente da consistência do histórico de alterações do objeto. Tenha cuidado ao preparar os dados para inserção. Dados inconsistentes podem produzir resultados imprevisíveis, como valores negativos para métricas não negativas, como a profundidade da sessão.

Algoritmo

Quando o ClickHouse faz o merge das partes de dados, ele exclui cada par de linhas que tenha a mesma chave primária e a mesma versão, mas Sign diferente. A ordem das linhas não importa. Quando o ClickHouse insere dados, ele ordena as linhas pela chave primária. Se a coluna Version não estiver na chave primária, o ClickHouse a adiciona implicitamente a ela como o último campo e a usa para ordenação.

Seleção de dados

O ClickHouse não garante que todas as linhas com a mesma chave primária ficarão na mesma parte de dados resultante, nem sequer no mesmo servidor físico. Isso vale tanto para a gravação dos dados quanto para a mesclagem posterior das partes de dados. Além disso, o ClickHouse processa consultas SELECT com várias threads e não consegue prever a ordem das linhas no resultado. Isso significa que a agregação é necessária quando for preciso obter dados totalmente “colapsados” de uma tabela VersionedCollapsingMergeTree. Para concluir o colapsamento, escreva uma consulta com uma cláusula GROUP BY e funções de agregação que levem em conta o sinal. Por exemplo, para calcular a quantidade, use sum(Sign) em vez de count(). Para calcular a soma de algum valor, use sum(Sign * x) em vez de sum(x) e adicione HAVING sum(Sign) > 0. Os agregados count, sum e avg podem ser calculados dessa forma. O agregado uniq pode ser calculado se um objeto tiver pelo menos um estado não colapsado. Os agregados min e max não podem ser calculados porque o VersionedCollapsingMergeTree não salva o histórico dos valores dos estados colapsados. Se você precisar extrair os dados com “colapsamento”, mas sem agregação (por exemplo, para verificar se há linhas cujos valores mais recentes correspondem a determinadas condições), poderá usar o modificador FINAL na cláusula FROM. Essa abordagem é ineficiente e não deve ser usada com tabelas grandes.

Exemplo de uso

Dados de exemplo:
Criando a tabela:
Inserção dos dados:
Usamos duas consultas INSERT para criar duas partes de dados diferentes. Se inserirmos os dados em uma única consulta, o ClickHouse criará apenas uma parte de dados e nunca fará nenhum merge. Obtendo os dados:
O que vemos aqui e onde estão as partes colapsadas? Criamos duas partes de dados usando duas consultas INSERT. A consulta SELECT foi executada em duas threads, e o resultado é uma ordem aleatória das linhas. O colapsamento não ocorreu porque as partes de dados ainda não foram mescladas. O ClickHouse mescla partes de dados em algum momento imprevisível, que não podemos prever. É por isso que precisamos de agregação:
Se não precisarmos de agregação e quisermos forçar o colapsamento, podemos usar o modificador FINAL na cláusula FROM.
Esta é uma forma muito ineficiente de selecionar dados. Não a use em tabelas grandes.
Última modificação em 23 de julho de 2026