Cuándo usar el tipo JSON
JSON está diseñado para consultar, filtrar y agregar campos específicos dentro de objetos JSON con estructuras dinámicas o impredecibles. Lo consigue dividiendo los objetos JSON en sub-columnas independientes, lo que reduce drásticamente la cantidad de datos leídos y acelera las consultas sobre los campos seleccionados en comparación con alternativas como Map o analizar cadenas.
Sin embargo, esto conlleva desventajas importantes:
INSERTs más lentos - Dividir el JSON en sub-columnas, realizar la inferencia de tipos y gestionar estructuras de almacenamiento flexibles hace que las inserciones sean más lentas que almacenar el JSON como una simple columnaString.- Más lento al leer objetos completos - Si necesita recuperar documentos JSON completos (en lugar de campos específicos), el tipo
JSONes más lento que leer desde una columnaString. La sobrecarga de reconstruir objetos a partir de sub-columnas independientes no aporta ningún beneficio cuando no se realizan consultas a nivel de campo. - Sobrecarga de almacenamiento - Mantener sub-columnas independientes añade sobrecarga estructural en comparación con almacenar JSON como un único valor de cadena.
Usa el tipo JSON cuando:
- Tus datos tienen una estructura dinámica o impredecible, con claves que varían entre documentos
- Los tipos de los campos o los esquemas cambian con el tiempo o varían entre registros
- Necesitas consultar, filtrar o agregar sobre rutas específicas dentro de objetos JSON cuya estructura no puedes predecir de antemano
- Tu caso de uso incluye datos semiestructurados, como logs, eventos o contenido generado por los usuarios, con esquemas inconsistentes
Usa una columna String (o tipos estructurados) cuando:
- La estructura de tus datos es conocida y consistente; en este caso, usa columnas normales o tipos
Tuple,Array,DynamicoVariant - Los documentos
JSONse tratan como blobs opacos que solo se almacenan y recuperan completos, sin análisis a nivel de campo - No necesitas consultar ni filtrar campos individuales de
JSONdentro de la base de datos JSONes simplemente un formato de transporte/almacenamiento y no se analiza dentro de ClickHouse
Consideraciones y consejos para usar JSON
- Especifique los tipos de las rutas mediante indicaciones en la definición de la columna para los subcolumnas conocidas y así evitar inferencias de tipo innecesarias.
- Omita rutas si no necesita sus valores, con SKIP y SKIP REGEXP, para reducir el almacenamiento y mejorar el rendimiento.
- Evite configurar
max_dynamic_pathscon un valor demasiado alto: los valores grandes aumentan el consumo de recursos y reducen la eficiencia. Como regla general, manténgalo por debajo de 10.000.
Indicaciones de tipoLas indicaciones de tipo ofrecen más que una forma de evitar inferencias de tipo innecesarias: eliminan por completo la indirección de almacenamiento y procesamiento. Las rutas JSON con indicaciones de tipo siempre se almacenan igual que las columnas tradicionales, sin necesidad de columnas discriminadoras ni de resolución dinámica en tiempo de consulta. Esto significa que, con indicaciones de tipo bien definidas, los campos JSON anidados alcanzan el mismo rendimiento y la misma eficiencia que si se hubieran modelado como campos de nivel superior desde el principio. Como resultado, para datasets que son en su mayoría consistentes pero que aun así se benefician de la flexibilidad de JSON, las indicaciones de tipo ofrecen una forma práctica de preservar el rendimiento sin necesidad de reestructurar el esquema ni el pipeline para ingestar datos.
Funciones avanzadas
- Las columnas JSON pueden usarse en claves primarias como cualquier otra columna. No se pueden especificar codecs para una subcolumna.
- Admiten introspección mediante funciones como
JSONAllPathsWithTypes()yJSONDynamicPaths(). - Puede leer subobjetos anidados con la sintaxis
.^. - La sintaxis de consulta puede diferir del SQL estándar y puede requerir conversiones de tipo especiales u operadores para los campos anidados.
Ejemplos
tags. Si fuera simplemente una lista de cadenas, podríamos modelarla como un Array(String), pero supongamos que se pueden añadir estructuras de etiquetas arbitrarias con tipos mixtos (obsérvese que score puede ser una cadena o un entero). Nuestro documento JSON modificado:
tags. A continuación, proporcionamos ambos ejemplos:
Proporcionamos una indicación de tipo para la columna
update_date en la definición de JSON, ya que la usamos en la clave de ordenación/clave primaria. Esto ayuda a ClickHouse a saber que esta columna no será nula y garantiza que sepa qué subcolumna update_date debe usar (puede haber varias para cada tipo, por lo que, de lo contrario, sería ambiguo).JSONAllPathsWithTypes y el formato de salida PrettyJSONEachRow:
tags. En general, esta opción es preferible, ya que minimiza la inferencia que debe realizar ClickHouse:
tags.