Quando usar o tipo JSON
JSON foi projetado para consultar, filtrar e agregar campos específicos em objetos JSON com estruturas dinâmicas ou imprevisíveis. Ele faz isso dividindo objetos JSON em subcolunas separadas, o que reduz drasticamente a quantidade de dados lidos e acelera as consultas em campos selecionados em comparação com alternativas como Map ou o parsing de strings.
No entanto, isso envolve trade-offs importantes:
INSERTs mais lentos - Dividir JSON em subcolunas, realizar inferência de tipos e gerenciar estruturas de armazenamento flexíveis torna os inserts mais lentos em comparação com armazenar JSON como uma simples colunaString.- Mais lento ao ler objetos inteiros - Se você precisa recuperar documentos JSON completos (em vez de campos específicos), o tipo
JSONé mais lento do que ler de uma colunaString. A sobrecarga de reconstruir objetos a partir de subcolunas separadas não traz nenhum benefício quando você não está fazendo consultas no nível de campo. - Sobrecarga de armazenamento - Manter subcolunas separadas acrescenta uma sobrecarga estrutural em comparação com armazenar JSON como um único valor em string.
Use o tipo JSON quando:
- Seus dados têm uma estrutura dinâmica ou imprevisível, com chaves que variam entre documentos
- Os tipos de campo ou os esquemas mudam ao longo do tempo ou variam entre registros
- Você precisa consultar, filtrar ou agregar dados em caminhos específicos dentro de objetos JSON cuja estrutura não pode ser prevista antecipadamente
- Seu caso de uso envolve dados semiestruturados, como logs, eventos ou conteúdo gerado por usuários, com esquemas inconsistentes
Use uma coluna String (ou tipos estruturados) quando:
- A estrutura dos seus dados é conhecida e consistente — nesse caso, use colunas normais ou os tipos
Tuple,Array,DynamicouVariant - Documentos
JSONsão tratados como blobs opacos, apenas armazenados e recuperados integralmente, sem análise em nível de campo - Você não precisa consultar nem filtrar campos individuais do JSON dentro do banco de dados
- O
JSONé simplesmente um formato de transporte/armazenamento e não é analisado no ClickHouse
Considerações e dicas para usar JSON
- Especifique os tipos dos caminhos usando hints na definição da coluna para definir os tipos de subcolunas conhecidas e evitar inferência de tipos desnecessária.
- Ignore caminhos se você não precisar dos valores, com SKIP e SKIP REGEXP para reduzir o armazenamento e melhorar o desempenho.
- Evite definir
max_dynamic_pathscomo um valor muito alto — valores altos aumentam o consumo de recursos e reduzem a eficiência. Como regra prática, mantenha-o abaixo de 10.000.
Indicações de tipoIndicações de tipo oferecem mais do que apenas uma forma de evitar inferência de tipos desnecessária — elas eliminam por completo a indireção de armazenamento e processamento. Caminhos JSON com indicações de tipo são sempre armazenados como colunas tradicionais, sem a necessidade de colunas discriminadoras ou resolução dinâmica no momento da consulta. Isso significa que, com indicações de tipo bem definidas, campos JSON aninhados alcançam o mesmo desempenho e eficiência como se tivessem sido modelados como campos de nível superior desde o início. Como resultado, para conjuntos de dados que são em sua maioria consistentes, mas ainda se beneficiam da flexibilidade do JSON, indicações de tipo oferecem uma forma prática de preservar o desempenho sem precisar reestruturar seu esquema ou pipeline de ingestão.
Recursos avançados
- Colunas JSON podem ser usadas em chaves primárias como quaisquer outras colunas. Não é possível especificar codecs para uma subcoluna.
- Elas oferecem introspecção por meio de funções como
JSONAllPathsWithTypes()eJSONDynamicPaths(). - Você pode ler sub-objetos aninhados usando a sintaxe
.^. - A sintaxe de consulta pode diferir do SQL padrão e pode exigir conversões de tipo ou operadores especiais para campos aninhados.
Exemplos
tags seja adicionada. Se fosse apenas uma lista de strings, poderíamos modelá-la como Array(String), mas vamos supor que seja possível adicionar estruturas arbitrárias para as tags com tipos mistos (observe que score pode ser uma string ou um inteiro). Nosso documento JSON modificado:
tags. Fornecemos os dois exemplos abaixo:
Fornecemos uma indicação de tipo para a coluna
update_date na definição de JSON, pois a usamos na chave de ordenação/chave primária. Isso ajuda o ClickHouse a saber que essa coluna não terá valor NULL e garante que ele saiba qual subcoluna update_date usar (pode haver várias para cada tipo, portanto, sem isso, haveria ambiguidade).JSONAllPathsWithTypes e o formato de saída PrettyJSONEachRow:
tags. Em geral, essa é a opção preferida, pois minimiza a inferência que o ClickHouse precisa fazer:
tags.