MergeTree e outros motores da família MergeTree (por exemplo, ReplacingMergeTree, AggregatingMergeTree) são os motores de tabela mais usados e mais robustos no ClickHouse.
Os motores de tabela da família MergeTree foram projetados para altas taxas de ingestão de dados e volumes massivos de dados.
As operações de inserção criam partes de tabela, que são mescladas por um processo em segundo plano com outras partes de tabela.
Principais recursos dos motores de tabela da família MergeTree.
- A chave primária da tabela determina a ordem de classificação dentro de cada parte de tabela (índice clusterizado). A chave primária também não faz referência a linhas individuais, mas a blocos de 8192 linhas chamados grânulos. Isso torna as chaves primárias de grandes conjuntos de dados pequenas o suficiente para permanecerem carregadas na memória principal, ao mesmo tempo em que ainda fornecem acesso rápido aos dados em disco.
- As tabelas podem ser particionadas usando uma expressão de partição arbitrária. O partition pruning garante que as partições sejam excluídas da leitura quando a consulta permitir.
- Os dados podem ser replicados em vários nós do cluster para alta disponibilidade, failover e upgrades sem indisponibilidade. Consulte Replicação de dados.
-
Os motores de tabela
MergeTreeoferecem suporte a vários tipos de estatísticas e métodos de amostragem para ajudar na otimização de consultas.
Apesar do nome semelhante, o motor Merge é diferente dos motores
*MergeTree.Criando tabelas
Cláusulas de consulta
ENGINE
ENGINE — Nome e parâmetros do motor. ENGINE = MergeTree(). O motor MergeTree não tem parâmetros.
ORDER BY
ORDER BY — A chave de ordenação.
Uma tupla de nomes de colunas ou expressões arbitrárias. Exemplo: ORDER BY (CounterID + 1, EventDate).
Se nenhuma chave primária estiver definida (ou seja, PRIMARY KEY não tiver sido especificada), ClickHouse usa a chave de ordenação como chave primária.
Se nenhuma ordenação for necessária, você pode usar a sintaxe ORDER BY tuple().
Como alternativa, se a configuração create_table_empty_primary_key_by_default estiver habilitada, ORDER BY () é adicionado implicitamente às instruções CREATE TABLE. Consulte Selecionando uma chave primária.
PARTITION BY
PARTITION BY — A chave de particionamento. Opcional. Na maioria dos casos, você não precisa de uma chave de particionamento e, se precisar particionar, em geral não precisa de uma chave de particionamento com granularidade maior do que por mês. O particionamento não acelera as consultas (ao contrário da expressão ORDER BY). Nunca use um particionamento granular demais. Não particione seus dados por identificadores ou nomes de clientes (em vez disso, use o identificador ou nome do cliente como a primeira coluna na expressão ORDER BY).
Para particionar por mês, use a expressão toYYYYMM(date_column), em que date_column é uma coluna com uma data do tipo Date. Os nomes das partições aqui têm o formato "YYYYMM".
PRIMARY KEY — A chave primária, se for diferente da chave de ordenação. Opcional.
Especificar uma chave de ordenação (usando a cláusula ORDER BY) implica especificar também uma chave primária.
Em geral, não é necessário especificar a chave primária além da chave de ordenação.
SAMPLE BY
SAMPLE BY — Uma expressão de amostragem. Opcional.
Se for especificada, deve estar contida na chave primária.
A expressão de amostragem deve resultar em um inteiro sem sinal.
Exemplo: SAMPLE BY intHash32(UserID) ORDER BY (CounterID, EventDate, intHash32(UserID)).
TTL
TTL — Uma lista de regras que especificam a duração do armazenamento das linhas e a lógica de movimentação automática de partes entre disks e volumes. Opcional.
A expressão deve resultar em um Date ou DateTime, por exemplo, TTL date + INTERVAL 1 DAY.
O tipo de regra DELETE|TO DISK 'xxx'|TO VOLUME 'xxx'|GROUP BY especifica uma ação a ser executada com a parte se a expressão for satisfeita (atingir o momento atual): remoção de linhas expiradas, movimentação de uma parte (se a expressão for satisfeita para todas as linhas de uma parte) para o disk especificado (TO DISK 'xxx') ou para o volume (TO VOLUME 'xxx'), ou agregação de valores nas linhas expiradas. O tipo padrão da regra é remoção (DELETE). É possível especificar uma lista com várias regras, mas não deve haver mais de uma regra DELETE.
Para mais detalhes, consulte TTL para colunas e tabelas
CONFIGURAÇÕES
CounterID e EventDate. Se você definir uma cláusula SAMPLE ao selecionar os dados, o ClickHouse retornará uma amostra de dados pseudorrandômica uniforme para um subconjunto de usuários.
A configuração index_granularity pode ser omitida, porque 8192 é o valor padrão.
Armazenamento de dados
(CounterID, Date), os dados da parte serão ordenados por CounterID e, dentro de cada CounterID, por Date.
Os dados pertencentes a partições diferentes são separados em partes diferentes. Em segundo plano, o ClickHouse mescla as partes de dados para tornar o armazenamento mais eficiente. Partes pertencentes a partições diferentes não são mescladas. O mecanismo de mesclagem não garante que todas as linhas com a mesma chave primária fiquem na mesma parte de dados.
As partes de dados podem ser armazenadas no formato Wide ou Compact. No formato Wide, cada coluna é armazenada em um arquivo separado em um sistema de arquivos; no formato Compact, todas as colunas são armazenadas em um único arquivo. O formato Compact pode ser usado para aumentar o desempenho de inserções pequenas e frequentes.
O formato de armazenamento dos dados é controlado pelas configurações min_bytes_for_wide_part e min_rows_for_wide_part do mecanismo da tabela. Se o número de bytes ou de linhas em uma parte de dados for menor que o valor da configuração correspondente, a parte será armazenada no formato Compact. Caso contrário, será armazenada no formato Wide. Se nenhuma dessas configurações estiver definida, as partes de dados serão armazenadas no formato Wide.
Cada parte de dados é dividida logicamente em grânulos. Um grânulo é o menor conjunto de dados indivisível que o ClickHouse lê ao selecionar dados. O ClickHouse não divide linhas nem valores, portanto cada grânulo sempre contém um número inteiro de linhas. A primeira linha de um grânulo é marcada com o valor da chave primária dessa linha. Para cada parte de dados, o ClickHouse cria um arquivo de índice que armazena as marcas. Para cada coluna, esteja ela na chave primária ou não, o ClickHouse também armazena as mesmas marcas. Essas marcas permitem localizar dados diretamente nos arquivos de coluna.
O tamanho do grânulo é limitado pelas configurações index_granularity e index_granularity_bytes do mecanismo da tabela. O número de linhas em um grânulo fica no intervalo [1, index_granularity], dependendo do tamanho das linhas. O tamanho de um grânulo pode exceder index_granularity_bytes se o tamanho de uma única linha for maior que o valor da configuração. Nesse caso, o tamanho do grânulo é igual ao tamanho da linha.
Chaves primárias e índices nas consultas
(CounterID, Date) como exemplo. Nesse caso, a ordenação e o índice podem ser ilustrados da seguinte forma:
CounterID in ('a', 'h'), o servidor lê os dados nos intervalos de marcas[0, 3)e[6, 8).CounterID IN ('a', 'h') AND Date = 3, o servidor lê os dados nos intervalos de marcas[1, 3)e[7, 8).Date = 3, o servidor lê os dados no intervalo de marcas[1, 10].
index_granularity * 2 linhas adicionais em cada bloco de dados podem ser lidas.
Índices esparsos permitem trabalhar com um número muito grande de linhas na tabela porque, na maioria dos casos, esses índices cabem na RAM do computador.
O ClickHouse não exige uma chave primária exclusiva. Você pode inserir várias linhas com a mesma chave primária.
Você pode usar expressões do tipo Nullable nas cláusulas PRIMARY KEY e ORDER BY, mas isso é fortemente desaconselhado. Para permitir esse recurso, ative a configuração allow_nullable_key. O princípio NULLS_LAST se aplica aos valores NULL na cláusula ORDER BY.
Selecionando uma chave primária
-
Melhorar o desempenho de um índice.
Se a chave primária for
(a, b), adicionar outra colunacmelhorará o desempenho se as seguintes condições forem atendidas:- Houver consultas com uma condição na coluna
c. - Forem comuns intervalos longos de dados (várias vezes maiores que a
index_granularity) com valores idênticos para(a, b). Em outras palavras, quando adicionar outra coluna permite pular intervalos de dados bastante longos.
- Houver consultas com uma condição na coluna
- Melhorar a compressão dos dados. O ClickHouse ordena os dados pela chave primária, portanto, quanto maior a consistência, melhor a compressão.
- Fornecer lógica adicional ao mesclar partes de dados nos motores CollapsingMergeTree e SummingMergeTree. Nesse caso, faz sentido especificar a chave de ordenação diferente da chave primária.
SELECT.
Você pode criar uma tabela sem chave primária usando a sintaxe ORDER BY tuple(). Nesse caso, o ClickHouse armazena os dados na ordem de inserção. Se você quiser preservar a ordem dos dados ao inseri-los com consultas INSERT ... SELECT, defina max_insert_threads = 1.
Para selecionar dados na ordem original, use consultas SELECT single-threaded.
Escolhendo uma chave primária diferente da chave de ordenação
GROUP BY arbitrário e filtragem por dimensões. Como SummingMergeTree e AggregatingMergeTree agregam linhas com o mesmo valor da chave de ordenação, é natural adicionar todas as dimensões a ela. Como resultado, a expressão de chave passa a consistir em uma longa lista de colunas, e essa lista precisa ser atualizada com frequência à medida que novas dimensões são adicionadas.
Nesse caso, faz sentido manter apenas algumas colunas na chave primária para garantir varreduras de intervalo eficientes e adicionar as colunas de dimensão restantes à tupla da chave de ordenação.
O ALTER da chave de ordenação é uma operação leve porque, quando uma nova coluna é adicionada simultaneamente à tabela e à chave de ordenação, as partes de dados existentes não precisam ser alteradas. Como a chave de ordenação antiga é um prefixo da nova chave de ordenação e não há dados na coluna recém-adicionada, os dados ficam ordenados tanto pela chave de ordenação antiga quanto pela nova no momento da modificação da tabela.
Uso de índices e partições em consultas
SELECT, o ClickHouse analisa se um índice pode ser usado. Um índice pode ser usado se a cláusula WHERE/PREWHERE contiver uma expressão (como um dos elementos da conjunção ou por completo) que represente uma operação de comparação de igualdade ou desigualdade, ou se contiver IN ou LIKE com um prefixo fixo em colunas ou expressões que façam parte da chave primária ou da chave de particionamento, ou em determinadas funções parcialmente repetitivas dessas colunas, ou em relações lógicas entre essas expressões.
Assim, é possível executar rapidamente consultas em um ou vários intervalos da chave primária. Neste exemplo, as consultas serão rápidas quando executadas para uma tag de rastreamento específica, para uma tag específica e um intervalo de datas, para uma tag específica e uma data, para várias tags com um intervalo de datas e assim por diante.
Vamos analisar o motor configurado da seguinte forma:
Uso do índice para expressões determinísticas em chaves primárias
length(), toDate(), lower(), left(), cityHash64(), toUUID(); ao contrário de now() ou rand()). Se a chave primária contiver expressões determinísticas, o ClickHouse poderá aplicá-las a valores constantes da consulta e usar o resultado para criar condições no índice da chave primária. Isso permite ignorar dados para predicados como =, IN e has.
Um caso de uso comum é manter a chave primária compacta (por exemplo, armazenar um hash em vez de uma String longa), ao mesmo tempo em que se permite que predicados na coluna original usem o índice.
Exemplo de uma chave primária determinística (mas não injetiva):
length('alice') (e outras constantes) uma vez e usa os valores de comprimento para restringir os intervalos no índice da chave primária. Como o comprimento de uma string não é injetivo, diferentes strings user_id podem ter o mesmo comprimento, então o índice pode ler grânulos extras (falsos positivos). O resultado permanece correto porque o predicado original (user_id = ..., IN etc.) ainda é aplicado após a leitura.
Se a expressão determinística também for injetiva (entradas diferentes não podem produzir a mesma saída para os tipos de argumento usados), o ClickHouse também pode usar o índice de forma eficaz para as formas negadas: !=, NOT IN e NOT has(...). Por exemplo, reverse(p) e hex(p) são injetivas para String.
Exemplo de uma chave primária injetiva:
Uso de índice para chaves primárias parcialmente monotônicas
Data skipping indexes
CREATE.
*MergeTree, é possível especificar data skipping indexes.
Esses índices agregam algumas informações sobre a expressão especificada em blocos, que consistem em granularity_value grânulos (o tamanho do grânulo é especificado usando a configuração index_granularity no engine da tabela). Em seguida, esses agregados são usados em consultas SELECT para reduzir a quantidade de dados a ser lida do disco, descartando grandes blocos de dados em que a condição da cláusula WHERE não pode ser satisfeita.
A cláusula GRANULARITY pode ser omitida; o valor padrão de granularity_value é 1.
Exemplo
Tipos de Skip Index
MergeTree oferece suporte aos seguintes tipos de skip indexes.
Para mais informações sobre como os skip indexes podem ser usados na otimização de desempenho,
consulte “Entendendo os data skipping indexes do ClickHouse”.
- índice
MinMax - índice
Set - índice
bloom_filter - índice
ngrambf_v1(Obsoleto) - índice
tokenbf_v1(Obsoleto) - índice
text - índice
vector_similarity
Índice skip do tipo MinMax
tuple, são armazenados os valores mínimo e máximo de cada elemento da tupla.)
Syntax
Set
max_rows valores únicos da expressão especificada.
max_rows = 0 significa “armazenar todos os valores únicos”.
Syntax
Filtro de Bloom
Syntax
false_positive_rate pode assumir um valor entre 0 e 1 (por padrão: 0.025) e especifica a probabilidade de gerar um resultado positivo (o que aumenta a quantidade de dados a serem lidos).
Os seguintes tipos de dados são suportados:
(U)Int*Float*EnumDateDateTimeStringFixedStringArrayLowCardinalityNullableUUIDMap
Tipo de dado JSON: indexando caminhos JSONPara o tipo de dado
JSON, um índice de filtro de Bloom pode ser criado sobre o conjunto de caminhos usando a função JSONAllPaths. Isso permite ignorar grânulos em que um caminho JSON consultado está ausente. Consulte Data skipping indexes para JSON para mais detalhes.Filtro de Bloom de n-gramas (Obsoleto)
Com a disponibilidade geral (GA) do índice
text a partir da versão 26.2 do ClickHouse, o índice ngrambf_v1 não é mais recomendado para busca em texto completo.Consulte a página “Busca em texto completo com índices de texto” para mais detalhes.Syntax
Este índice só funciona com os seguintes tipos de dados:
Para estimar os parâmetros de
ngrambf_v1, você pode usar as seguintes Funções Definidas pelo Usuário (UDFs).
UDFs for ngrambf_v1
total_number_of_all_gramsprobability_of_false_positives
4300 ngrams no grânulo, e você espera que os falsos positivos sejam inferiores a 0.0001.
Os outros parâmetros podem então ser estimados executando as seguintes consultas:
Filtro de Bloom de token
Com a disponibilidade geral (GA) do índice
text a partir da versão 26.2 do ClickHouse, o índice tokenbf_v1 não é mais recomendado para busca em texto completo.Consulte a página “Pesquisa de texto completo com índices de texto” para mais detalhes.Syntax
Filtro de Bloom de gramas esparsos
ngrambf_v1, mas usa tokens de gramas esparsos em vez de ngrams.
Syntax
Índice de texto
Similaridade vetorial
Suporte a funções
WHERE contêm chamadas a funções que operam sobre colunas. Se a coluna fizer parte de um índice, o ClickHouse tentará usar esse índice ao processar essas funções. O ClickHouse oferece suporte a diferentes subconjuntos de funções para o uso de índices.
Índices do tipo set podem ser usados por todas as funções. Os demais tipos de índice têm suporte conforme a seguir:
Funções com um argumento constante menor que o tamanho do ngram não podem ser usadas por
ngrambf_v1 para otimização de consultas.
(*) Para que hasTokenCaseInsensitive e hasTokenCaseInsensitiveOrNull sejam eficazes, o índice tokenbf_v1 deve ser criado sobre dados convertidos para minúsculas, por exemplo INDEX idx (lower(str_col)) TYPE tokenbf_v1(512, 3, 0).
Filtros de Bloom podem gerar falsos positivos, portanto os índices
ngrambf_v1, tokenbf_v1, sparse_grams e bloom_filter não podem ser usados para otimizar consultas em que se espera que o resultado de uma função seja falso.Por exemplo:- Pode ser otimizado:
s LIKE '%test%'NOT s NOT LIKE '%test%'s = 1NOT s != 1startsWith(s, 'test')
- Não pode ser otimizado:
NOT s LIKE '%test%'s NOT LIKE '%test%'NOT s = 1s != 1NOT startsWith(s, 'test')
Projeções
Ao implementar projeções, você também deve considerar a configuração force_optimize_projection.
SELECT com o modificador FINAL.
Consulta de projeção
Índices de projeção
_part_offset, ou seja, SELECT _part_offset ORDER BY <index_expr>.
Sintaxe
Tipos de índice
- básico: equivalente a um índice normal do MergeTree sobre a expressão.
Armazenamento de projeções
MergeTree anônima. A tabela é derivada da consulta de definição da projeção. Se houver uma cláusula GROUP BY, o motor de armazenamento subjacente se torna AggregatingMergeTree, e todas as funções de agregação são convertidas em AggregateFunction. Se houver uma cláusula ORDER BY, a tabela MergeTree a usa como expressão de chave primária. Durante o processo de merge, a parte da projeção é mesclada pela rotina de merge do seu motor de armazenamento. O checksum da parte da tabela pai é combinado com a parte da projeção. Outras tarefas de manutenção são semelhantes às dos índices de salto.
Análise de consulta
- Verifique se a projeção pode ser usada para responder à consulta fornecida, ou seja, se ela gera a mesma resposta que consultar a tabela base.
- Selecione a melhor opção viável, que contenha o menor número de grânulos a serem lidos.
- O pipeline de consulta que usa projeções será diferente daquele que usa as partes originais. Se a projeção estiver ausente em algumas partes, podemos adicionar um pipeline para “projetá-la” dinamicamente.
Acesso simultâneo aos dados
TTL para colunas e tabelas
TTL pode ser definida para a tabela inteira e para cada coluna individual. O TTL no nível da tabela também pode especificar a lógica de movimentação automática de dados entre disks e volumes, ou a recompressão de partes cujos dados já expiraram.
As expressões devem resultar em um tipo de dado Date, Date32, DateTime ou DateTime64.
Sintaxe
Definir o time-to-live de uma coluna:
interval, use os operadores de intervalo de tempo, por exemplo:
TTL de coluna
TTL não pode ser usada para colunas de chave.
Exemplos
Criando uma tabela com TTL:
Adicionando TTL a uma coluna em uma tabela existente
Alterar o TTL da coluna
TTL da tabela
TTL.
TTL pode acompanhar cada expressão TTL. Ele determina a ação a ser executada quando a expressão for satisfeita (atingir o momento atual):
DELETE- exclui linhas expiradas (ação padrão);RECOMPRESS codec_name- recomprime a parte de dados com ocodec_name;TO DISK 'aaa'- move a part para o diskaaa;TO VOLUME 'bbb'- move a part para o diskbbb;GROUP BY- agrega linhas expiradas.
DELETE pode ser usada em conjunto com a cláusula WHERE para excluir apenas algumas das linhas expiradas com base em uma condição de filtragem:
GROUP BY deve ser um prefixo da chave primária da tabela.
Se uma coluna não fizer parte da expressão GROUP BY e não for definida explicitamente na cláusula SET, ela conterá, na linha de resultado, um valor aleatório das linhas agrupadas (como se a função de agregação any fosse aplicada a ela).
Exemplos
Criando uma tabela com TTL:
Alterando o TTL da tabela:
Criando uma tabela em que as linhas expiradas são recomprimidas:
x contém o valor máximo entre as linhas agrupadas, y, o valor mínimo, e d, um valor qualquer das linhas agrupadas.
Remoção de dados expirados
TTL expirado são removidos quando o ClickHouse faz a mesclagem de partes de dados.
Quando o ClickHouse detecta que os dados expiraram, ele realiza uma mesclagem fora do cronograma. Para controlar a frequência dessas mesclagens, você pode definir merge_with_ttl_timeout. Se o valor for muito baixo, muitas mesclagens fora do cronograma serão executadas, o que pode consumir muitos recursos.
Se você executar a consulta SELECT entre as mesclagens, poderá obter dados expirados. Para evitar isso, use a consulta OPTIMIZE antes de SELECT.
Veja também
- configuração ttl_only_drop_parts
Tipos de disco
s3para S3 e MinIOgcspara GCSblob_storage_diskpara Azure Blob Storagehdfspara HDFSwebpara somente leitura via webcachepara cache locals3_plainpara backups no S3s3_plain_rewritablepara tabelas imutáveis e não replicadas no S3
Uso de vários dispositivos de bloco para armazenamento de dados
Introdução
MergeTree podem armazenar dados em vários dispositivos de bloco. Por exemplo, isso pode ser útil quando os dados de uma determinada tabela são implicitamente divididos em “quentes” e “frios”. Os dados mais recentes são consultados com frequência, mas exigem apenas uma pequena quantidade de espaço. Por outro lado, o grande volume de dados históricos é consultado raramente. Se houver vários disks disponíveis, os dados “quentes” podem ficar em disks rápidos (por exemplo, SSDs NVMe ou em memória), enquanto os dados “frios” ficam em disks relativamente lentos (por exemplo, HDDs).
Isso se aplica a todos os tipos de disco, incluindo disks S3 e outros disks de armazenamento de objetos. Por exemplo, você pode distribuir dados entre vários buckets do S3 em um único volume ou criar políticas em camadas que movem dados de disks locais para o S3. Veja Usando disks S3 com vários volumes para mais detalhes.
Uma parte de dados é a menor unidade móvel das tabelas com motor MergeTree. Os dados pertencentes a uma parte são armazenados em um único disco. As partes de dados podem ser movidas entre disks em segundo plano (de acordo com as configurações do usuário), bem como por meio das consultas ALTER.
Termos
- Disco — Dispositivo de bloco montado no sistema de arquivos.
- Disco padrão — Disco que armazena o caminho especificado na configuração de servidor path.
- Volume — Conjunto ordenado de disks idênticos (semelhante a JBOD).
- Política de armazenamento — Conjunto de volumes e das regras para mover dados entre eles.
storage_policy das tabelas da família de engines MergeTree.
Configuração
<storage_configuration>, em um arquivo no diretório config.d.
Estrutura da configuração:
<disk_name_N>— Nome do disco. Os nomes devem ser diferentes para todos os disks.path— caminho no qual o servidor armazenará os dados (pastasdataeshadow); deve terminar com ’/’.keep_free_space_bytes— quantidade de espaço livre em disco a ser reservada.
policy_name_N— Nome da política. Os nomes das políticas devem ser únicos.volume_name_N— Nome do volume. Os nomes dos volumes devem ser únicos.disk— um disco dentro de um volume.max_data_part_size_bytes— o tamanho máximo de uma parte que pode ser armazenada em qualquer um dos disks do volume. Se o tamanho estimado de uma parte de dados mesclada for maior quemax_data_part_size_bytes, essa parte será gravada no próximo volume. Basicamente, esse recurso permite manter partes novas/pequenas em um volume quente (SSD) e movê-las para um volume frio (HDD) quando atingirem um tamanho grande. Não use essa configuração se sua política tiver apenas um volume.move_factor— quando a quantidade de espaço disponível fica abaixo desse fator, os dados começam automaticamente a ser movidos para o próximo volume, se houver (por padrão, 0.1). O ClickHouse classifica as partes existentes por tamanho, da maior para a menor (em ordem decrescente), e seleciona partes cujo tamanho total seja suficiente para atender à condição demove_factor. Se o tamanho total de todas as partes for insuficiente, todas as partes serão movidas.perform_ttl_move_on_insert— Desabilita o TTL move no INSERT de partes de dados. Por padrão (se estiver habilitado), se inserirmos uma parte de dados que já expirou pela regra de TTL move, ela irá imediatamente para um volume/disco declarado na regra de movimentação. Isso pode tornar o insert significativamente mais lento caso o volume/disco de destino seja lento (por exemplo, S3). Se estiver desabilitado, a parte de dados já expirada será gravada em um volume padrão e, logo em seguida, movida para o volume de TTL.load_balancing- Política de balanceamento de disks,round_robinouleast_used.least_used_ttl_ms- Configura o timeout (em milissegundos) para a atualização do espaço disponível em todos os disks (0- sempre atualizar,-1- nunca atualizar, o padrão é60000). Observe que, se o disco puder ser usado apenas pelo ClickHouse e não estiver sujeito a redimensionamento/redução online do filesystem, você pode usar-1; em todos os outros casos, isso não é recomendado, pois eventualmente levará a uma distribuição incorreta do espaço.prefer_not_to_merge— Você não deve usar essa configuração. Desabilita a mesclagem de partes de dados neste volume (isso é prejudicial e leva à degradação de desempenho). Quando essa configuração está habilitada (não faça isso), a mesclagem de dados neste volume não é permitida (o que é ruim). Isso permite (mas você não precisa disso) controlar (se você quiser controlar alguma coisa, está cometendo um erro) como o ClickHouse funciona com disks lentos (mas o ClickHouse sabe mais, então, por favor, não use essa configuração).volume_priority— Define a prioridade (ordem) em que os volumes são preenchidos. Um valor menor significa prioridade maior. Os valores do parâmetro devem ser números naturais e, em conjunto, cobrir o intervalo de 1 a N (sendo N a menor prioridade atribuída) sem pular nenhum número.- Se todos os volumes estiverem marcados, eles serão priorizados na ordem fornecida.
- Se apenas alguns volumes estiverem marcados, os que não tiverem a marcação terão a menor prioridade e serão priorizados na ordem em que são definidos na configuração.
- Se nenhum volume estiver marcado, sua prioridade será definida de acordo com a ordem em que for declarado na configuração.
- Dois volumes não podem ter o mesmo valor de prioridade.
hdd_in_order implementa a abordagem de round-robin. Assim, essa política define apenas um volume (single), e as partes de dados são armazenadas em todos os seus disks em ordem circular. Essa política pode ser bastante útil se houver vários disks semelhantes montados no sistema, mas o RAID não estiver configurado. Tenha em mente que cada disco individual não é confiável, e talvez você queira compensar isso com um fator de replicação de 3 ou mais.
Se houver diferentes tipos de disks disponíveis no sistema, a política moving_from_ssd_to_hdd pode ser usada no lugar. O volume hot consiste em um disco SSD (fast_ssd), e o tamanho máximo de uma parte que pode ser armazenada nesse volume é 1GB. Todas as partes com tamanho maior que 1GB serão armazenadas diretamente no volume cold, que contém um disco HDD disk1.
Além disso, quando o disco fast_ssd ficar mais de 80% cheio, os dados serão transferidos para disk1 por um processo em segundo plano.
A ordem de enumeração dos volumes dentro de uma política de armazenamento é importante caso pelo menos um dos volumes listados não tenha um parâmetro volume_priority explícito.
Quando um volume fica cheio demais, os dados são movidos para o próximo. A ordem de enumeração dos disks também é importante, porque os dados são armazenados neles em rodízio.
Ao criar uma tabela, é possível aplicar a ela uma das políticas de armazenamento configuradas:
default pressupõe o uso de apenas um volume, que consiste em apenas um disco definido em <path>.
Você pode alterar a política de armazenamento após a criação da tabela com a consulta [ALTER TABLE … MODIFY SETTING], e a nova política deve incluir todos os disks e volumes antigos com os mesmos nomes.
O número de threads que executam movimentações em segundo plano de partes de dados pode ser alterado pela configuração background_move_pool_size.
Detalhes
MergeTree, os dados chegam ao disco de diferentes maneiras:
- Como resultado de um insert (consulta
INSERT). - Durante mesclagens em segundo plano e mutações.
- Ao serem baixados de outra réplica.
- Como resultado do congelamento de uma partição ALTER TABLE … FREEZE PARTITION.
- É escolhido o primeiro volume (na ordem de definição) que tenha espaço em disco suficiente para armazenar uma parte (
unreserved_space > current_part_size) e permita armazenar partes de determinado tamanho (max_data_part_size_bytes > current_part_size). - Dentro desse volume, é escolhido o disco que vem após o usado para armazenar o fragmento anterior de dados e que tenha espaço livre maior que o tamanho da parte (
unreserved_space - keep_free_space_bytes > current_part_size).
move_factor), de acordo com a ordem em que os volumes são declarados no arquivo de configuração.
Os dados nunca são transferidos do último para o primeiro. É possível usar as tabelas de sistema system.part_log (campo type = MOVE_PART) e system.parts (campos path e disk) para monitorar movimentações em segundo plano. Além disso, informações detalhadas podem ser encontradas nos logs do servidor.
O usuário pode forçar a movimentação de uma parte ou de uma partição de um volume para outro usando a consulta ALTER TABLE … MOVE PART|PARTITION … TO VOLUME|DISK …; todas as restrições das operações em segundo plano são levadas em consideração. A consulta inicia a movimentação por conta própria e não espera a conclusão das operações em segundo plano. O usuário receberá uma mensagem de erro se não houver espaço livre suficiente ou se alguma das condições exigidas não for atendida.
A movimentação de dados não interfere na replicação. Portanto, diferentes políticas de armazenamento podem ser especificadas para a mesma tabela em réplicas diferentes.
Após a conclusão das mesclagens em segundo plano e das mutações, as partes antigas só são removidas depois de um certo tempo (old_parts_lifetime).
Durante esse período, elas não são movidas para outros volumes ou disks. Portanto, até que sejam finalmente removidas, ainda são consideradas no cálculo do espaço em disco ocupado.
O usuário pode distribuir novas partes grandes entre diferentes disks de um volume JBOD de forma equilibrada usando a configuração min_bytes_to_rebalance_partition_over_jbod.
Usando armazenamento externo para dados
S3, AzureBlobStorage e HDFS usando, respectivamente, discos dos tipos s3, azure_blob_storage e hdfs. Consulte como configurar opções de armazenamento externo para mais detalhes.
Exemplo de uso do S3 como armazenamento externo com um disco do tipo s3.
Trecho de configuração:
Usando disks do S3 com vários volumes
Ao usar
use_environment_credentials para autenticação no S3, as credenciais de ambiente (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN) são compartilhadas entre todos os disks S3. Não é possível usar credenciais de ambiente diferentes para disks diferentes. Se você precisar de credenciais diferentes para cada disk S3, use as configurações explícitas access_key_id e secret_access_key para cada disco.table_disk = true com um disco local da tabela). Consulte refresh_parts_interval and table_disk.
configuração do cacheAs versões 22.3 a 22.7 do ClickHouse usam uma configuração de cache diferente. Consulte using local cache se você estiver usando uma dessas versões.
Colunas virtuais
_part— Nome de uma parte._part_index— Índice sequencial da parte no resultado da consulta._part_starting_offset— Linha inicial cumulativa da parte no resultado da consulta._part_offset— Número da linha na parte._part_granule_offset— Número do grânulo na parte._partition_id— Nome de uma partição._part_uuid— Identificador exclusivo da parte (se a configuração do MergeTreeassign_part_uuidsestiver habilitada)._part_data_version— Versão dos dados da parte (seja o número mínimo do bloco ou a versão da mutação)._partition_value— Valores (uma tupla) de uma expressãopartition by._sample_factor— Fator de amostragem (da consulta)._block_number— Número original do bloco da linha que foi atribuído na inserção, persistido em mesclagens quando a configuraçãoenable_block_number_columnestá habilitada._block_offset— Número original da linha no bloco que foi atribuído na inserção, persistido em mesclagens quando a configuraçãoenable_block_offset_columnestá habilitada._disk_name— Nome do disco usado para o armazenamento.
Estatísticas de coluna
CREATE para tabelas da família *MergeTree*:
ALTER:
set use_statistics = 1.
Poda de partes com estatísticas
use_statistics_for_part_pruning está habilitado, as estatísticas podem ser usadas para a poda de partes.
Atualmente, apenas as estatísticas basic (e as estatísticas minmax obsoletas) dão suporte à poda de partes. Quando essas estatísticas são definidas para uma coluna, o ClickHouse acompanha os valores mínimo e máximo dessa coluna em cada parte.
A poda de partes permite evitar a leitura de partes de dados inteiras quando a condição de filtro da consulta não pode corresponder a nenhuma linha nessa parte.
Exemplo:
Tipos disponíveis de estatísticas de coluna
-
basicUm conjunto compacto de resumos de valor único derivados de uma coluna. Dependendo do tipo da coluna, os seguintes elementos são preenchidos:-
para qualquer coluna cujos valores sejam representados por um número (inteiros, floats,
Decimal*,Date*,DateTime*,Enum*,IPv4, …): os valores mínimo e máximo, que permitem estimar a seletividade de filtros por intervalo e habilitam a poda de partes; -
para colunas
StringeFixedString: o comprimento total em bytes dos valores nãoNULL(a partir do qual é possível derivar o comprimento médio das strings); -
para colunas
NullableeLowCardinality(Nullable): a contagem de valoresNULL, que o otimizador usa para descontar linhasNULLdas estimativas de seletividade. Uma única estatísticabasicpode preencher vários desses elementos ao mesmo tempo — por exemplo, em uma colunaNullable(UInt32), ela rastreia tanto o mínimo/máximo numérico quanto a contagem de nulos. Em comparação comminmax,basictambém funciona em colunasString/FixedStringe pode ser declarada em wrappersNullablede tipos comoUUIDouIPv6apenas para rastrear a contagem de nulos.
-
para qualquer coluna cujos valores sejam representados por um número (inteiros, floats,
-
minmax(obsoleto)
As estatísticas
minmax estão obsoletas e não podem mais ser criadas (CREATE TABLE ... STATISTICS(minmax) e ALTER TABLE ... ADD/MODIFY STATISTICS ... TYPE minmax retornam um erro). Tabelas e partes existentes com estatísticas minmax continuam funcionando. Use estatísticas basic no lugar.tdigest
-
uniqSketches BJKST que fornecem uma estimativa de quantos valores distintos uma coluna contém. Internamente, usauniq. -
uniq_v2Semelhante auniq, mas internamente usauniqCombined(12)(uma variante de HyperLogLog). Consome menos memória queuniqe pode ser compilado mais rapidamente. -
countmin
Tipos de dados suportados
Todos os itens acima também aceitam wrappers
Nullable e LowCardinality(Nullable) dos tipos listados. Basic também pode ser declarado em wrappers Nullable de tipos como UUID ou IPv6 exclusivamente para rastrear a contagem de valores nulos.
Operações suportadas
Para
basic em colunas String / FixedString, a estatística registra apenas o comprimento total, em bytes, dos valores não NULL
(usado para estimar o comprimento médio da string) e a contagem de nulos;
filtros por intervalo e poda de partes não usam essa estatística.
Configurações em nível de coluna
max_compress_block_size— Tamanho máximo dos blocos de dados não comprimidos antes de serem comprimidos para gravação em uma tabela.min_compress_block_size— Tamanho mínimo dos blocos de dados não comprimidos necessário para que a compressão ocorra ao gravar a próxima marca.
- Remova
SETTINGSda declaração da coluna:
- Altere uma configuração:
- Restaura uma ou mais configurações e também remove a declaração da configuração na expressão de coluna da consulta CREATE da tabela.