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

> Documentación sobre el formato Native

# Native

| Entrada | Salida | Alias |
| ------- | ------ | ----- |
| ✔       | ✔      |       |

<div id="description">
  ## Descripción
</div>

El formato `Native` es el formato más eficiente de ClickHouse porque es realmente "columnar",
ya que no convierte las columnas en filas.

En este formato, los datos se escriben y se leen por [bloques](/es/resources/develop-contribute/introduction/architecture#block) en formato binario.
Para cada bloque, se registran uno tras otro el número de filas, el número de columnas, los nombres y tipos de las columnas, y las partes de las columnas del bloque.

Este es el formato que se utiliza en la interfaz nativa para la interacción entre servidores, para usar el cliente de línea de comandos y para los clientes de C++.

<Tip>
  Puede usar este formato para generar rápidamente volcados que solo puede leer el sistema de gestión de bases de datos ClickHouse.
  Puede que no resulte práctico trabajar directamente con este formato.
</Tip>

<div id="data-types-wire-format">
  ## Formato wire de los tipos de datos
</div>

Los datos se envían por el wire en un formato columnar, lo que significa que cada columna se envía por separado
y que todos los valores de una columna se envían juntos como un único array.

Cada columna de un bloque contiene un encabezado similar a [RowBinaryWithNamesAndTypes](/es/reference/formats/RowBinary/RowBinaryWithNamesAndTypes).

<Note>
  Al usar el protocolo binario TCP nativo (o cuando el endpoint HTTP recibe `?client_protocol_version=<n>`),
  se escribe una estructura `BlockInfo` antes del recuento de columnas y filas. Los ejemplos de esta sección usan
  la interfaz HTTP simple, sin versión de protocolo, por lo que se omite `BlockInfo`.
</Note>

<div id="block-structure">
  ### Estructura del bloque
</div>

La siguiente consulta devuelve dos columnas, `number` y `str`, con tres filas:

```bash theme={null}
curl -XPOST "http://localhost:8123?default_format=Native" --data-binary "SELECT number, toString(number) AS str FROM system.numbers LIMIT 3" > out.bin
```

Los datos de salida caben en un solo bloque de ClickHouse y tendrán este aspecto:

```js theme={null}
const data = new Uint8Array([
  // --- Encabezado de bloque ---
  0x02,                   // 2 columnas
  0x03,                   // 3 filas
  // -- Encabezado de columna 1 --
  0x06,                   // LEB128 - el nombre de columna 'number' tiene 6 bytes
  0x6e, 0x75, 0x6d,       
  0x62, 0x65, 0x72,       // nombre de columna: 'number'
  0x06,                   // LEB128 - el tipo de columna 'UInt64' tiene 6 bytes
  0x55, 0x49, 0x6e,
  0x74, 0x36, 0x34,       // 'UInt64'
  0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, // 0 como UInt64
  0x01, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, // 1 como UInt64
  0x02, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, // 2 como UInt64
  0x03,                   // LEB128 - el nombre de columna 'str' tiene 3 bytes
  0x73, 0x74, 0x72,       // nombre de columna: 'str'
  0x06,                   // LEB128 - el tipo de columna 'String' tiene 6 bytes
  0x53, 0x74, 0x72, 
  0x69, 0x6e, 0x67,       // 'String'
  0x01,                   // LEB128 - la cadena tiene 1 byte
  0x30,                   // '0' como String
  0x01,                   // LEB128 - la cadena tiene 1 byte
  0x31,                   // '1' como String
  0x01,                   // LEB128 - la cadena tiene 1 byte
  0x32,                   // '2' como String
])
```

<div id="multiple-blocks">
  ### Múltiples bloques
</div>

Sin embargo, en muchos casos, los datos no cabrán en un solo bloque, y ClickHouse los enviará en varios bloques.
Considere la siguiente consulta, que recupera dos filas con un tamaño de bloque reducido para forzar que los datos se dividan en una fila por bloque:

```bash theme={null}
curl -XPOST "http://localhost:8123?default_format=Native" --data-binary "SELECT number, toString(number) AS str                FROM system.numbers LIMIT 2                 SETTINGS max_block_size=1" \  > out.bin
```

La salida:

```js theme={null}
const data = new Uint8Array([
 
  // ----- Bloque 1 ----- 
  0x02,                   // 2 columnas
  0x01,                   // 1 fila
  0x06,                   // LEB128 - el nombre de columna 'number' tiene 6 bytes
  0x6E, 0x75, 0x6D, 
  0x62, 0x65, 0x72,       // nombre de columna: 'number' 
  0x06,                   // LEB128 - el tipo de columna 'UInt64' tiene 6 bytes
  0x55, 0x49, 0x6E, 
  0x74, 0x36, 0x34,       // 'UInt64' 
  0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, // 0 como UInt64
  0x03,                   // LEB128 - el nombre de columna 'str' tiene 3 bytes
  0x73, 0x74, 0x72,       // nombre de columna: 'str'
  0x06,                   // LEB128 - el tipo de columna 'String' tiene 6 bytes
  0x53, 0x74, 0x72, 
  0x69, 0x6E, 0x67,       // 'String'
  0x01,                   // LEB128 - la cadena tiene 1 byte
  0x30,                   // '0' como String
  
  // ----- Bloque 2 -----
  0x02,                   // 2 columnas
  0x01,                   // 1 fila
  0x06,                   // LEB128 - el nombre de columna 'number' tiene 6 bytes
  0x6E, 0x75, 0x6D,  
  0x62, 0x65, 0x72,       // nombre de columna: 'number'
  0x06,                   // LEB128 - el tipo de columna 'UInt64' tiene 6 bytes
  0x55, 0x49, 0x6E,  
  0x74, 0x36, 0x34,       // 'UInt64'
  0x01, 0x00, 0x00, 0x00,  
  0x00, 0x00, 0x00, 0x00, // 1 como UInt64
  0x03,                   // LEB128 - el nombre de columna 'str' tiene 3 bytes
  0x73, 0x74, 0x72,       // nombre de columna: 'str'
  0x06,                   // LEB128 - el tipo de columna 'String' tiene 6 bytes
  0x53, 0x74, 0x72,  
  0x69, 0x6E, 0x67,       // 'String'
  0x01,                   // LEB128 - la cadena tiene 1 byte
  0x31,                   // '1' como String
]);
```

<div id="simple-data-types">
  ### Tipos de datos simples
</div>

El formato wire de un valor individual de uno de los tipos de datos simples es similar a `RowBinary`/`RowBinaryWithNamesAndTypes`.
La lista completa de tipos que se ajustan a esta descripción incluye:

* (U)Int8, (U)Int16, (U)Int32, (U)Int64, (U)Int128, (U)Int256
* Float32, Float64
* Bool
* String
* FixedString(N)
* Date
* Date32
* DateTime
* DateTime64
* IPv4
* IPv6
* UUID

Consulta las descripciones de los tipos anteriores en ["Formato wire de los tipos de datos de RowBinary"](/es/reference/formats/RowBinary/RowBinary#data-types-wire-format) para obtener más información.

<div id="complex-data-types">
  ### Tipos de datos complejos
</div>

La codificación de los siguientes tipos de datos difiere de `RowBinary` y `RowBinaryWithNamesAndTypes`.

* Nullable
* LowCardinality
* Array
* Map
* Variant
* Dynamic
* JSON

<div id="nullable">
  #### Nullable
</div>

En el formato `Native`, una columna Nullable tendrá un número de bytes igual al número de filas del bloque antes de los datos propiamente dichos. Cada uno de estos bytes indica si el valor es `NULL` o no. Por ejemplo, con esta consulta, cada número impar será `NULL`:

```bash theme={null}
curl -XPOST "http://localhost:8123?default_format=Native" \  --data-binary "SELECT if(number % 2 = 0, number, NULL) :: Nullable(UInt64) AS maybe_null                 FROM system.numbers LIMIT 5" \  > out.bin
```

La salida tendrá este aspecto:

```js theme={null}
const data = new Uint8Array([
  // --- Encabezado de bloque ---
  0x01,                         // LEB128 - 1 columna
  0x05,                         // LEB128 - 5 filas
  
  // -- Encabezado de columna --
  0x0A,                         // LEB128 - el nombre de columna tiene 10 bytes
  0x6D, 0x61, 0x79, 0x62, 0x65, 
  0x5F, 0x6E, 0x75, 0x6C, 0x6C, // nombre de columna: 'maybe_null'
  
  0x10,                         // LEB128 - el tipo de columna tiene 16 bytes
  0x4E, 0x75, 0x6C, 0x6C, 
  0x61, 0x62, 0x6C, 0x65, 
  0x28, 0x55, 0x49, 0x6E, 
  0x74, 0x36, 0x34, 0x29,       // tipo de columna: 'Nullable(UInt64)'
  
  // -- Máscara Nullable --
  0x00,                         // La fila 0 es NOT NULL
  0x01,                         // La fila 1 es NULL
  0x00,                         // La fila 2 es NOT NULL
  0x01,                         // La fila 3 es NULL
  0x00,                         // La fila 4 es NOT NULL
  
  // -- Valores UInt64 --
  0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00,       // Fila 0: 0 como UInt64

  // aunque pueda haber un valor válido para este número
  // en el bloque, igualmente debe devolverse como NULL al usuario.
  0x01, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,       // Fila #1: NULL
  
  0x02, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00,       // Fila #2: 2 como UInt64
  
  0x03, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00,       // Fila #3: NULL, similar a la fila #1
  
  0x04, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00,       // Fila #4: 4 como UInt64
]);
```

Funciona de forma similar con `Nullable(String)`. El indicador de nulo siempre proviene del byte de máscara de Nullable:
un valor de máscara de `0x01` significa que la fila es `NULL` independientemente del contenido de la cadena. En las filas `NULL`,
la cadena subyacente se almacena como una cadena vacía (longitud LEB128 `0`). Tenga en cuenta que una cadena vacía no `NULL`
también tiene una longitud LEB128 de `0`, por lo que solo el byte de máscara distingue ambos casos. Por ejemplo, la siguiente consulta:

```bash theme={null}
curl -XPOST "http://localhost:8123?default_format=Native" \  --data-binary "SELECT if(number % 2 = 0, toString(number), NULL) :: Nullable(String) AS maybe_str                 FROM system.numbers LIMIT 5" \  > out.bin
```

La salida tendrá este aspecto:

```js theme={null}
const data = new Uint8Array([
  // --- Encabezado de bloque ---
  0x01, // LEB128 - 1 columna
  0x05, // LEB128 - 5 filas

  // -- Encabezado de columna --
  0x09, // LEB128 - el nombre de columna tiene 9 bytes
  0x6d,
  0x61,
  0x79,
  0x62,
  0x65,
  0x5f,
  0x73,
  0x74,
  0x72, // nombre de columna: 'maybe_str'

  0x10, // LEB128 - el tipo de columna tiene 16 bytes
  0x4e,
  0x75,
  0x6c,
  0x6c,
  0x61,
  0x62,
  0x6c,
  0x65,
  0x28,
  0x53,
  0x74,
  0x72,
  0x69,
  0x6e,
  0x67,
  0x29, // tipo de columna: 'Nullable(String)'

  // -- Máscara Nullable --
  0x00, // Fila 0 es NOT NULL
  0x01, // Fila 1 es NULL
  0x00, // Fila 2 es NOT NULL
  0x01, // Fila 3 es NULL
  0x00, // Fila 4 es NOT NULL

  // -- Valores String --
  0x01,
  0x30, // Fila 0: LEB128 == 1, '0' como String
  0x00, // Fila 1: LEB128 == 0, NULL
  0x01,
  0x32, // Fila 2: LEB128 == 1, '2' como String
  0x00, // Fila 3: LEB128 == 0, NULL
  0x01,
  0x34, // Fila 4: LEB128 == 1, '4' como String
])
```

<div id="lowcardinality">
  #### LowCardinality
</div>

A diferencia de [RowBinary](/es/reference/formats/RowBinary/RowBinary#lowcardinality), donde `LowCardinality` es transparente, el formato Native utiliza una codificación columnar basada en diccionario. Una columna se codifica como un prefijo de versión, seguido de un diccionario de valores únicos y un array de índices enteros dentro de ese diccionario.

<Note>
  Una columna puede definirse como `LowCardinality(Nullable(T))`, pero no es posible definirla como `Nullable(LowCardinality(T))` — siempre dará como resultado un error del servidor.
</Note>

El prefijo de versión es un `UInt64(LE)` con valor `1`, escrito una vez por columna. Luego, por bloque, se escribe lo siguiente:

* `UInt64(LE)` — campo de bits `IndexesSerializationType`. Los bits 0–7 codifican el ancho del índice (0 = UInt8, 1 = UInt16, 2 = UInt32, 3 = UInt64). El bit 8 (`NeedGlobalDictionaryBit`) nunca se establece en el formato Native (el servidor genera una excepción si lo encuentra). El bit 9 indica que hay claves de diccionario adicionales presentes. El bit 10 indica que el diccionario debe restablecerse.
* `UInt64(LE)` — número de claves del diccionario, seguido de las claves serializadas en bloque mediante la codificación del tipo interno.
* `UInt64(LE)` — número de filas, seguido de los valores de índice serializados en bloque usando el ancho de UInt correspondiente.

El diccionario siempre contiene un valor predeterminado en el índice 0 (por ejemplo, una cadena vacía para `String`, 0 para los tipos numéricos). Para `LowCardinality(Nullable(T))`, el índice 0 representa `NULL`, y las claves se serializan sin el contenedor `Nullable`.

Por ejemplo, `LowCardinality(String)` con 5 filas `['foo', 'bar', 'baz', 'foo', 'bar']`:

```text theme={null}
// Prefijo de versión
01 00 00 00 00 00 00 00    // UInt64(LE) = 1

// IndexesSerializationType: índices UInt8, tiene claves, actualizar diccionario
00 06 00 00 00 00 00 00    // UInt64(LE) = 0x0600

04 00 00 00 00 00 00 00    // 4 claves del diccionario
00                          // clave 0: "" (predeterminado)
03 66 6f 6f                 // clave 1: "foo"
03 62 61 72                 // clave 2: "bar"
03 62 61 7a                 // clave 3: "baz"

05 00 00 00 00 00 00 00    // 5 filas
01 02 03 01 02              // índices → "foo", "bar", "baz", "foo", "bar"
```

Con `LowCardinality(Nullable(String))`, el índice 0 es `NULL`:

```text theme={null}
01 00 00 00 00 00 00 00    // versión
00 06 00 00 00 00 00 00    // IndexesSerializationType
03 00 00 00 00 00 00 00    // 3 claves
00                          // clave 0: NULL
00                          // clave 1: "" (predeterminado)
03 79 65 73                 // clave 2: "yes"
05 00 00 00 00 00 00 00    // 5 filas
02 00 02 00 02              // índices → "yes", NULL, "yes", NULL, "yes"
```

<div id="array">
  #### Array
</div>

A diferencia de [RowBinary](/es/reference/formats/RowBinary/RowBinary#array), donde cada array va precedido de un recuento LEB128 del número de elementos, el formato Native codifica los arrays como dos subflujos columnares:

* N offsets `UInt64` acumulativos (`little-endian`, 8 bytes cada uno). La fila `i` tiene `offset[i] - offset[i-1]` elementos, con `offset[-1]` implícitamente igual a 0.
* Todos los elementos anidados de todas las filas, serializados en bloque de forma contigua.

Por ejemplo, `Array(UInt32)` con 3 filas `[[0, 10], [1, 11], [2, 12]]`:

```text theme={null}
// Desplazamientos
02 00 00 00 00 00 00 00    // 2 (fila 0: 2 elementos)
04 00 00 00 00 00 00 00    // 4 (fila 1: 2 elementos)
06 00 00 00 00 00 00 00    // 6 (fila 2: 2 elementos)

// Valores UInt32 anidados (6 en total)
00 00 00 00                 // 0
0a 00 00 00                 // 10
01 00 00 00                 // 1
0b 00 00 00                 // 11
02 00 00 00                 // 2
0c 00 00 00                 // 12
```

Un array vacío tiene el mismo desplazamiento que la fila anterior. Por ejemplo, `Array(String)` con 4 filas `[[], ['0'], ['0','1'], ['0','1','2']]`:

```text theme={null}
00 00 00 00 00 00 00 00    // 0 (vacío)
01 00 00 00 00 00 00 00    // 1
03 00 00 00 00 00 00 00    // 3
06 00 00 00 00 00 00 00    // 6
01 30                       // "0"
01 30                       // "0"
01 31                       // "1"
01 30                       // "0"
01 31                       // "1"
01 32                       // "2"
```

<div id="map">
  #### Map
</div>

Un `Map(K, V)` se codifica como `Array(Tuple(K, V))` — offsets del array, seguidos de todas las claves y luego de todos los valores. Esto difiere de [RowBinary](/es/reference/formats/RowBinary/RowBinary#map), donde las claves y los valores se intercalan en cada entrada.

Por ejemplo, `Map(String, UInt64)` con 3 filas `[{'a':0,'b':10}, {'a':1,'b':11}, {'a':2,'b':12}]`:

```text theme={null}
// Desplazamientos del array
02 00 00 00 00 00 00 00    // 2
04 00 00 00 00 00 00 00    // 4
06 00 00 00 00 00 00 00    // 6

// Todas las claves (6 Strings)
01 61                       // "a"
01 62                       // "b"
01 61                       // "a"
01 62                       // "b"
01 61                       // "a"
01 62                       // "b"

// Todos los valores (6 UInt64s)
00 00 00 00 00 00 00 00    // 0
0a 00 00 00 00 00 00 00    // 10
01 00 00 00 00 00 00 00    // 1
0b 00 00 00 00 00 00 00    // 11
02 00 00 00 00 00 00 00    // 2
0c 00 00 00 00 00 00 00    // 12
```

<div id="variant">
  #### Variant
</div>

A diferencia de [RowBinary](/es/reference/formats/RowBinary/RowBinary#variant), donde cada fila lleva su propio byte discriminante seguido del valor en línea, el formato Native separa los discriminantes de los datos.

<Warning>
  Al igual que en RowBinary, los tipos de la definición siempre se ordenan alfabéticamente, y el discriminante es el índice dentro de esa lista ordenada. `0xFF` (255) representa `NULL`.
</Warning>

Una columna `Variant` se codifica de la siguiente manera:

* Prefijo del modo de discriminadores `UInt64(LE)` (`0` = BASIC, `1` = COMPACT). La salida del formato Native suele usar BASIC (`0`); el modo COMPACT puede aparecer al leer datos almacenados con `use_compact_variant_discriminators_serialization` activado.
* N discriminadores `UInt8`, uno por fila.
* Los datos de cada tipo de variante como una columna en bloque independiente que contiene solo las filas correspondientes, en orden de discriminante.

Por ejemplo, `Variant(String, UInt32)` con 5 filas `[0::UInt32, 'hello', NULL, 3::UInt32, 'hello']` (ordenados: `String` = 0, `UInt32` = 1):

```text theme={null}
00 00 00 00 00 00 00 00    // modo de discriminadores = BASIC
01 00 ff 01 00              // UInt32, String, NULL, UInt32, String

// String (2 valores, filas 1 y 4)
05 68 65 6c 6c 6f          // "hello"
05 68 65 6c 6c 6f          // "hello"

// UInt32 (2 valores, filas 0 y 3)
00 00 00 00                 // 0
03 00 00 00                 // 3
```

<div id="dynamic">
  #### Dynamic
</div>

A diferencia de [RowBinary](/es/reference/formats/RowBinary/RowBinary#dynamic), donde cada valor es autodescriptivo (prefijo de tipo + valor), el formato Native serializa `Dynamic` como un prefijo de estructura seguido de una columna [Variant](#variant).

El prefijo de estructura contiene una versión de serialización `UInt64(LE)`, luego el número de tipos dinámicos (como VarUInt) y, a continuación, los nombres de los tipos como cadenas. En la versión V1, el recuento de tipos se escribe dos veces por compatibilidad. Los datos que siguen corresponden a una columna `Variant` cuya lista de tipos incluye los tipos dinámicos más un tipo interno `SharedVariant`, ordenados alfabéticamente.

Por ejemplo, `Dynamic` con 5 filas `[0::UInt32, 'hello', NULL, 3::UInt32, 'hello']`:

```text theme={null}
// Prefijo de estructura (V1)
01 00 00 00 00 00 00 00    // versión = V1
02                          // núm. de tipos (V1 escribe dos veces)
02                          // núm. de tipos
06 53 74 72 69 6e 67       // "String"
06 55 49 6e 74 33 32       // "UInt32"

// Datos Variant: Variant(SharedVariant, String, UInt32)
// discriminantes: SharedVariant=0, String=1, UInt32=2
00 00 00 00 00 00 00 00    // modo de discriminadores = BASIC
02 01 ff 02 01              // UInt32, String, NULL, UInt32, String
// SharedVariant: 0 valores
05 68 65 6c 6c 6f          // String: "hello"
05 68 65 6c 6c 6f          // String: "hello"
00 00 00 00                 // UInt32: 0
03 00 00 00                 // UInt32: 3
```

<div id="json">
  #### JSON
</div>

A diferencia de [RowBinary](/es/reference/formats/RowBinary/RowBinary#json), donde cada fila contiene su propia descripción con nombres de rutas y valores, el formato Native serializa `JSON` en una estructura columnar. La codificación es compleja y depende de la versión: consta de un prefijo de estructura con la versión de serialización, nombres de rutas dinámicas y la disposición de los datos compartidos, seguido de rutas tipadas (cada una como una columna en bloque), rutas dinámicas (cada una como una columna [Dynamic](#dynamic)) y datos compartidos para las rutas de desbordamiento.

Para una interoperabilidad más sencilla, considere usar la configuración `output_format_native_write_json_as_string=1`, que serializa las columnas JSON como cadenas de texto JSON simples (una `String` por fila).
