Introdução
Operação básica
- Nome do índice. O nome do índice é usado para criar o arquivo de índice em cada partição. Além disso, ele é necessário como parâmetro ao remover ou materializar o índice.
- Expressão do índice. A expressão do índice é usada para calcular o conjunto de valores armazenados no índice. Ela pode ser uma combinação de colunas, operadores simples e/ou um subconjunto de funções determinado pelo tipo de índice.
- TYPE. O tipo de índice controla o cálculo que determina se é possível pular a leitura e a avaliação de cada bloco de índice.
- GRANULARITY. Cada bloco indexado consiste em GRANULARITY grânulos. Por exemplo, se a granularidade do índice primário da tabela for de 8192 linhas, e a granularidade do índice for 4, cada “bloco” indexado terá 32768 linhas.
skp_idx_{index_name}.idx, que contém os valores ordenados da expressãoskp_idx_{index_name}.mrk2, que contém os deslocamentos correspondentes nos arquivos de dados das colunas associadas.
my_value
são varridas:
my_value igual a 125 foram lidas e selecionadas, e como as linhas seguintes
foram ignoradas sem precisar ser lidas do disco:
Você pode acessar informações detalhadas sobre o uso de skip indexes ativando o trace ao executar consultas. No
clickhouse-client, defina send_logs_level:
Tipos de índices de omissão
minmax
set
text
hasAnyToken e hasAllTokens, além de otimizar todas as funções comuns de busca em texto.
Consulte a documentação do índice de texto para mais detalhes aqui.
Tipos de filtro de Bloom
- O bloom_filter básico, que aceita um único parâmetro opcional para a taxa permitida de “falsos positivos”, entre 0 e 1 (se não for especificado, usa-se .025).
-
O tokenbf_v1 especializado (Obsoleto). Ele recebe três parâmetros, todos relacionados ao ajuste do filtro de Bloom usado: (1) o tamanho do filtro em bytes (filtros maiores geram menos falsos positivos, com algum custo de armazenamento), (2) o número de funções de hash aplicadas (novamente, mais funções de hash reduzem falsos positivos) e (3) a seed das funções de hash do filtro de Bloom. Veja a calculadora aqui para mais detalhes sobre como esses parâmetros afetam o funcionamento do filtro de Bloom.
Esse índice funciona apenas com os tipos de dados String, FixedString e Map. A expressão de entrada é dividida em sequências de caracteres separadas por caracteres não alfanuméricos. Por exemplo, um valor de coluna
This is a candidate for a "full text" searchconterá os tokensThisisacandidateforfulltextsearch. Ele foi projetado para uso em pesquisas LIKE, EQUALS, IN, hasToken() e semelhantes, para palavras e outros valores dentro de strings mais longas. Por exemplo, um uso possível seria pesquisar um pequeno número de nomes de classes ou números de linha em uma coluna de linhas de log de aplicação em formato livre. -
O ngrambf_v1 especializado (Obsoleto). Esse índice funciona da mesma forma que o índice de token. Ele recebe um parâmetro adicional antes das configurações do filtro de Bloom: o tamanho dos ngrams a indexar. Um ngram é uma sequência de caracteres de comprimento
n, composta por quaisquer caracteres; portanto, a stringA short string, com um tamanho de ngram igual a 4, seria indexada como:
Para workloads de busca em texto completo, recomenda-se o text index dedicado (consulte Text index for full-text search) em vez dos índices obsoletos tokenbf_v1 ou ngrambf_v1. O text index fornece um verdadeiro índice invertido, com melhor desempenho de busca, comportamento mais previsível e mais flexibilidade e desempenho em comparação com índices de filtro de Bloom baseados em token.
Funções de skip indexes
- os dados são inseridos e o índice é definido como uma expressão funcional (com o resultado da expressão armazenado nos arquivos de índice), ou
- a consulta é processada e a expressão é aplicada aos valores de índice armazenados para determinar se o bloco deve ser excluído.
Configurações de skip indexes
- use_skip_indexes (0 ou 1, padrão 1). Nem todas as consultas conseguem usar skip indexes com eficiência. Se uma determinada condição de filtragem provavelmente incluir a maioria dos grânulos, aplicar o índice de data skipping gera um custo desnecessário e, às vezes, significativo. Defina o valor como 0 para consultas que provavelmente não se beneficiarão de nenhum skip index.
- force_data_skipping_indices (lista de nomes de índices separados por vírgulas). Essa configuração pode ser usada para evitar alguns tipos de consultas ineficientes. Em situações em que consultar uma tabela é caro demais, a menos que um skip index seja usado, usar essa configuração com um ou mais nomes de índice fará com que seja retornada uma exceção para qualquer consulta que não use o índice listado. Isso evita que consultas mal escritas consumam recursos do servidor.
Boas práticas para skip indexes
timestamp e que exista um índice em visitor_id. Considere a seguinte consulta:
visitor_id serão testados
independentemente do tipo de skip index.
Consequentemente, o impulso natural de tentar acelerar consultas do ClickHouse simplesmente adicionando um índice às
colunas-chave geralmente está errado. Essa funcionalidade avançada só deve ser usada depois de investigar outras alternativas, como modificar a chave primária (consulte How to Pick a Primary Key), usar projeções ou usar visões materializadas. Mesmo quando um data skipping index é apropriado, muitas vezes será necessário ajustar cuidadosamente tanto o índice quanto a tabela.
Na maioria dos casos, um skip index útil exige uma forte correlação entre a chave primária e a coluna/expressão não primária de interesse.
Se não houver correlação (como no diagrama acima), as chances de que a condição de filtragem seja satisfeita por pelo menos uma das linhas no
bloco de vários milhares de valores é alta, e poucos blocos serão ignorados. Em contraste, se um intervalo de valores da chave primária (como a hora do
dia) estiver fortemente associado aos valores na possível coluna de índice (como idades de telespectadores), então um índice do tipo minmax
provavelmente será benéfico. Observe que pode ser possível aumentar essa correlação ao inserir dados, seja incluindo colunas adicionais
na chave de ordenação/ORDER BY, seja fazendo batching das inserções de modo que os valores associados à chave primária sejam agrupados na inserção. Por
exemplo, todos os eventos de um determinado site_id poderiam ser agrupados e inseridos juntos pelo processo de ingestão, mesmo que a chave primária
seja um timestamp contendo eventos de um grande número de sites. Isso resultará em muitos grânulos que contêm apenas alguns IDs de site, então muitos
blocos poderão ser ignorados ao pesquisar por um valor específico de site_id.
Outro bom candidato para um skip index são expressões de alta cardinalidade em que cada valor individual é relativamente esparso nos dados. Um exemplo
poderia ser uma plataforma de observabilidade que rastreia códigos de erro em requisições de API. Certos códigos de erro, embora raros nos dados, podem ser particularmente
importantes para buscas. Um skip index do tipo set na coluna error_code permitiria ignorar a grande maioria dos blocos que não contêm
erros e, portanto, melhorar significativamente consultas focadas em erros.
Por fim, a principal boa prática é testar, testar, testar. Novamente, ao contrário de índices secundários b-tree ou índices invertidos para busca em documentos,
o comportamento de um data skipping index não é facilmente previsível. Adicioná-los a uma tabela gera um custo significativo tanto na ingestão de dados quanto em consultas
que, por qualquer motivo, não se beneficiam do índice. Eles sempre devem ser testados em dados do mundo real, e os testes devem
incluir variações do tipo, do tamanho da granularidade e de outros parâmetros. Os testes frequentemente revelarão padrões e armadilhas que não são óbvios apenas com
experimentos mentais.