> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-fix-nav-issues.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Use JSON cuando sea apropiado

> Página que describe cuándo usar JSON

ClickHouse ahora ofrece un tipo de columna JSON nativo diseñado para datos semiestructurados y dinámicos. Es importante aclarar que **se trata de un tipo de columna, no de un formato de datos**: puedes insertar JSON en ClickHouse como una cadena o mediante formatos compatibles como [JSONEachRow](/es/reference/formats/JSON/JSONEachRow), pero eso no significa que estés usando el tipo de columna JSON. Solo debes usar el tipo JSON cuando la estructura de tus datos sea dinámica, no simplemente porque almacenes JSON.

<div id="when-to-use-json-type">
  ## Cuándo usar el tipo `JSON`
</div>

El tipo `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:**

* `INSERT`s 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 columna `String`.
* Más lento al leer objetos completos - Si necesita recuperar documentos JSON completos (en lugar de campos específicos), el tipo `JSON` es más lento que leer desde una columna `String`. 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.

<div id="use-json-type">
  ### Usa el tipo `JSON` cuando:
</div>

* 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

<div id="use-string-type">
  ### Usa una columna `String` (o tipos estructurados) cuando:
</div>

* La estructura de tus datos es conocida y consistente; en este caso, usa columnas normales o tipos `Tuple`, `Array`, `Dynamic` o `Variant`
* Los documentos `JSON` se 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 `JSON` dentro de la base de datos
* `JSON` es simplemente un formato de transporte/almacenamiento y no se analiza dentro de ClickHouse

<Tip>
  Si `JSON` es un documento opaco que no se analiza dentro de la base de datos y solo se almacena y se recupera, debe almacenarse como un campo `String`. Las ventajas del tipo `JSON` solo se materializan cuando necesitas consultar, filtrar o agregar de forma eficiente campos específicos dentro de estructuras `JSON` dinámicas.

  También puedes combinar ambos enfoques: usa columnas estándar para campos de nivel superior predecibles y una columna `JSON` para las secciones dinámicas del payload.
</Tip>

<div id="considerations-and-tips-for-using-json">
  ## Consideraciones y consejos para usar JSON
</div>

El tipo JSON permite un almacenamiento columnar eficiente al aplanar las rutas en subcolumnas. Pero la flexibilidad también conlleva responsabilidad. Para usarlo de forma eficaz:

* **Especifique los tipos de las rutas** mediante [indicaciones en la definición de la columna](/es/reference/data-types/newjson) para los subcolumnas conocidas y así evitar inferencias de tipo innecesarias.
* **Omita rutas** si no necesita sus valores, con [SKIP y SKIP REGEXP](/es/reference/data-types/newjson), para reducir el almacenamiento y mejorar el rendimiento.
* **Evite configurar [`max_dynamic_paths`](/es/reference/data-types/newjson#reaching-the-limit-of-dynamic-paths-inside-json) con 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.

<Info>
  **Indicaciones de tipo**

  Las 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**](https://clickhouse.com/blog/a-new-powerful-json-data-type-for-clickhouse#storage-extension-for-dynamically-changing-data) 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.
</Info>

<div id="advanced-features">
  ## Funciones avanzadas
</div>

* 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()` y `JSONDynamicPaths()`](/es/reference/data-types/newjson#introspection-functions).
* 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.

Para obtener más información, consulte[ la documentación de JSON de ClickHouse](/es/reference/data-types/newjson) o lea nuestra entrada del blog[ A New Powerful JSON Data Type for ClickHouse](https://clickhouse.com/blog/a-new-powerful-json-data-type-for-clickhouse).

<div id="examples">
  ## Ejemplos
</div>

Considere el siguiente ejemplo en JSON, que representa una fila del [Python PyPI dataset](https://clickpy.clickhouse.com/):

```json theme={null}
{
  "date": "2022-11-15",
  "country_code": "ES",
  "project": "clickhouse-connect",
  "type": "bdist_wheel",
  "installer": "pip",
  "python_minor": "3.9",
  "system": "Linux",
  "version": "0.3.0"
}
```

Supongamos que este esquema es estático y que los types pueden definirse con claridad. Aunque los datos estén en format NDJSON (una fila JSON por línea), no es necesario usar el tipo JSON para un esquema así. Simplemente defina el esquema con types clásicos.

```sql theme={null}
CREATE TABLE pypi (
  `date` Date,
  `country_code` String,
  `project` String,
  `type` String,
  `installer` String,
  `python_minor` String,
  `system` String,
  `version` String
)
ENGINE = MergeTree
ORDER BY (project, date)
```

e insertar filas en JSON:

```sql theme={null}
INSERT INTO pypi FORMAT JSONEachRow
{"date":"2022-11-15","country_code":"ES","project":"clickhouse-connect","type":"bdist_wheel","installer":"pip","python_minor":"3.9","system":"Linux","version":"0.3.0"}
```

Considere el [conjunto de datos de arXiv](https://www.kaggle.com/datasets/Cornell-University/arxiv?resource=download), que contiene 2,5 millones de artículos académicos. Cada fila de este conjunto de datos, distribuido en formato NDJSON, representa un artículo académico publicado. A continuación se muestra una fila de ejemplo:

```json theme={null}
{
  "id": "2101.11408",
  "submitter": "Daniel Lemire",
  "authors": "Daniel Lemire",
  "title": "Number Parsing at a Gigabyte per Second",
  "comments": "Software at https://github.com/fastfloat/fast_float and\n  https://github.com/lemire/simple_fastfloat_benchmark/",
  "journal-ref": "Software: Practice and Experience 51 (8), 2021",
  "doi": "10.1002/spe.2984",
  "report-no": null,
  "categories": "cs.DS cs.MS",
  "license": "http://creativecommons.org/licenses/by/4.0/",
  "abstract": "With disks and networks providing gigabytes per second ....\n",
  "versions": [
    {
      "created": "Mon, 11 Jan 2021 20:31:27 GMT",
      "version": "v1"
    },
    {
      "created": "Sat, 30 Jan 2021 23:57:29 GMT",
      "version": "v2"
    }
  ],
  "update_date": "2022-11-07",
  "authors_parsed": [
    [
      "Lemire",
      "Daniel",
      ""
    ]
  ]
}
```

Aunque el JSON aquí es complejo y tiene estructuras anidadas, es predecible. La cantidad y el tipo de los campos no cambiarán. Aunque podríamos usar el tipo JSON en este ejemplo, también podemos definir la estructura explícitamente mediante los tipos [Tuples](/es/reference/data-types/tuple) y [Nested](/es/reference/data-types/nested-data-structures):

```sql theme={null}
CREATE TABLE arxiv
(
  `id` String,
  `submitter` String,
  `authors` String,
  `title` String,
  `comments` String,
  `journal-ref` String,
  `doi` String,
  `report-no` String,
  `categories` String,
  `license` String,
  `abstract` String,
  `versions` Array(Tuple(created String, version String)),
  `update_date` Date,
  `authors_parsed` Array(Array(String))
)
ENGINE = MergeTree
ORDER BY update_date
```

De nuevo, podemos insertar los datos en formato JSON:

```sql theme={null}
INSERT INTO arxiv FORMAT JSONEachRow 
{"id":"2101.11408","submitter":"Daniel Lemire","authors":"Daniel Lemire","title":"Number Parsing at a Gigabyte per Second","comments":"Software at https://github.com/fastfloat/fast_float and\n  https://github.com/lemire/simple_fastfloat_benchmark/","journal-ref":"Software: Practice and Experience 51 (8), 2021","doi":"10.1002/spe.2984","report-no":null,"categories":"cs.DS cs.MS","license":"http://creativecommons.org/licenses/by/4.0/","abstract":"With disks and networks providing gigabytes per second ....\n","versions":[{"created":"Mon, 11 Jan 2021 20:31:27 GMT","version":"v1"},{"created":"Sat, 30 Jan 2021 23:57:29 GMT","version":"v2"}],"update_date":"2022-11-07","authors_parsed":[["Lemire","Daniel",""]]}
```

Supongamos que se añade otra columna llamada `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:

```sql theme={null}
{
 "id": "2101.11408",
 "submitter": "Daniel Lemire",
 "authors": "Daniel Lemire",
 "title": "Number Parsing at a Gigabyte per Second",
 "comments": "Software at https://github.com/fastfloat/fast_float and\n  https://github.com/lemire/simple_fastfloat_benchmark/",
 "journal-ref": "Software: Practice and Experience 51 (8), 2021",
 "doi": "10.1002/spe.2984",
 "report-no": null,
 "categories": "cs.DS cs.MS",
 "license": "http://creativecommons.org/licenses/by/4.0/",
 "abstract": "With disks and networks providing gigabytes per second ....\n",
 "versions": [
 {
   "created": "Mon, 11 Jan 2021 20:31:27 GMT",
   "version": "v1"
 },
 {
   "created": "Sat, 30 Jan 2021 23:57:29 GMT",
   "version": "v2"
 }
 ],
 "update_date": "2022-11-07",
 "authors_parsed": [
 [
   "Lemire",
   "Daniel",
   ""
 ]
 ],
 "tags": {
   "tag_1": {
     "name": "ClickHouse user",
     "score": "A+",
     "comment": "A good read, applicable to ClickHouse"
   },
   "28_03_2025": {
     "name": "professor X",
     "score": 10,
     "comment": "Didn't learn much",
     "updates": [
       {
         "name": "professor X",
         "comment": "Wolverine found more interesting"
       }
     ]
   }
 }
}
```

En este caso, podríamos modelar los documentos de arXiv íntegramente en JSON o simplemente añadir una columna JSON `tags`. A continuación, proporcionamos ambos ejemplos:

```sql theme={null}
CREATE TABLE arxiv
(
  `doc` JSON(update_date Date)
)
ENGINE = MergeTree
ORDER BY doc.update_date
```

<Note>
  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).
</Note>

Podemos insertar datos en esta tabla y ver el esquema inferido a continuación usando la función [`JSONAllPathsWithTypes`](/es/reference/functions/regular-functions/json-functions#JSONAllPathsWithTypes) y el formato de salida [`PrettyJSONEachRow`](/es/reference/formats/JSON/PrettyJSONEachRow):

```sql theme={null}
INSERT INTO arxiv FORMAT JSONAsObject 
{"id":"2101.11408","submitter":"Daniel Lemire","authors":"Daniel Lemire","title":"Number Parsing at a Gigabyte per Second","comments":"Software at https://github.com/fastfloat/fast_float and\n  https://github.com/lemire/simple_fastfloat_benchmark/","journal-ref":"Software: Practice and Experience 51 (8), 2021","doi":"10.1002/spe.2984","report-no":null,"categories":"cs.DS cs.MS","license":"http://creativecommons.org/licenses/by/4.0/","abstract":"With disks and networks providing gigabytes per second ....\n","versions":[{"created":"Mon, 11 Jan 2021 20:31:27 GMT","version":"v1"},{"created":"Sat, 30 Jan 2021 23:57:29 GMT","version":"v2"}],"update_date":"2022-11-07","authors_parsed":[["Lemire","Daniel",""]],"tags":{"tag_1":{"name":"ClickHouse user","score":"A+","comment":"A good read, applicable to ClickHouse"},"28_03_2025":{"name":"professor X","score":10,"comment":"Didn't learn much","updates":[{"name":"professor X","comment":"Wolverine found more interesting"}]}}}
```

```sql theme={null}
SELECT JSONAllPathsWithTypes(doc)
FROM arxiv
FORMAT PrettyJSONEachRow

{
  "JSONAllPathsWithTypes(doc)": {
    "abstract": "String",
    "authors": "String",
    "authors_parsed": "Array(Array(Nullable(String)))",
    "categories": "String",
    "comments": "String",
    "doi": "String",
    "id": "String",
    "journal-ref": "String",
    "license": "String",
    "submitter": "String",
    "tags.28_03_2025.comment": "String",
    "tags.28_03_2025.name": "String",
    "tags.28_03_2025.score": "Int64",
    "tags.28_03_2025.updates": "Array(JSON(max_dynamic_types=16, max_dynamic_paths=256))",
    "tags.tag_1.comment": "String",
    "tags.tag_1.name": "String",
    "tags.tag_1.score": "String",
    "title": "String",
    "update_date": "Date",
    "versions": "Array(JSON(max_dynamic_types=16, max_dynamic_paths=256))"
  }
}

1 row in set. Elapsed: 0.003 sec.
```

Como alternativa, podríamos modelar esto utilizando nuestro esquema anterior y una columna JSON `tags`. En general, esta opción es preferible, ya que minimiza la inferencia que debe realizar ClickHouse:

```sql theme={null}
CREATE TABLE arxiv
(
    `id` String,
    `submitter` String,
    `authors` String,
    `title` String,
    `comments` String,
    `journal-ref` String,
    `doi` String,
    `report-no` String,
    `categories` String,
    `license` String,
    `abstract` String,
    `versions` Array(Tuple(created String, version String)),
    `update_date` Date,
    `authors_parsed` Array(Array(String)),
    `tags` JSON()
)
ENGINE = MergeTree
ORDER BY update_date
```

```sql theme={null}
INSERT INTO arxiv FORMAT JSONEachRow 
{"id":"2101.11408","submitter":"Daniel Lemire","authors":"Daniel Lemire","title":"Number Parsing at a Gigabyte per Second","comments":"Software at https://github.com/fastfloat/fast_float and\n  https://github.com/lemire/simple_fastfloat_benchmark/","journal-ref":"Software: Practice and Experience 51 (8), 2021","doi":"10.1002/spe.2984","report-no":null,"categories":"cs.DS cs.MS","license":"http://creativecommons.org/licenses/by/4.0/","abstract":"With disks and networks providing gigabytes per second ....\n","versions":[{"created":"Mon, 11 Jan 2021 20:31:27 GMT","version":"v1"},{"created":"Sat, 30 Jan 2021 23:57:29 GMT","version":"v2"}],"update_date":"2022-11-07","authors_parsed":[["Lemire","Daniel",""]],"tags":{"tag_1":{"name":"ClickHouse user","score":"A+","comment":"A good read, applicable to ClickHouse"},"28_03_2025":{"name":"professor X","score":10,"comment":"Didn't learn much","updates":[{"name":"professor X","comment":"Wolverine found more interesting"}]}}}
```

Ahora podemos inferir los tipos de la subcolumna `tags`.

```sql theme={null}
SELECT JSONAllPathsWithTypes(tags)
FROM arxiv
FORMAT PrettyJSONEachRow

{
  "JSONAllPathsWithTypes(tags)": {
    "28_03_2025.comment": "String",
    "28_03_2025.name": "String",
    "28_03_2025.score": "Int64",
    "28_03_2025.updates": "Array(JSON(max_dynamic_types=16, max_dynamic_paths=256))",
    "tag_1.comment": "String",
    "tag_1.name": "String",
    "tag_1.score": "String"
  }
}
```

```response theme={null}
1 row in set. Elapsed: 0.002 sec.
```
