> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> RowBinary フォーマットに関するドキュメント

# RowBinary

| 入力 | 出力 | エイリアス |
| -- | -- | ----- |
| ✔  | ✔  |       |

<div id="description">
  ## 説明
</div>

`RowBinary` フォーマットは、バイナリ形式のデータを行単位で解析します。
行と値は、区切り文字なしで連続して並びます。
データがバイナリ形式であるため、`FORMAT RowBinary` の後の区切り文字は以下のとおり厳密に定められています。

* 任意の数の空白文字:
  * `' '` (スペース - コード `0x20`)
  * `'\t'` (タブ - コード `0x09`)
  * `'\f'` (フォームフィード - コード `0x0C`)
* その後に、ちょうど 1 つの改行シーケンス:
  * Windows 形式 `"\r\n"`
  * または Unix 形式 `'\n'`
* その直後にバイナリデータ。

<Note>
  このフォーマットは行ベースであるため、[Native](/docs/ja/reference/formats/Native) フォーマットよりも効率が低くなります。
</Note>

<div id="data-types-wire-format">
  ## データ型のワイヤ形式
</div>

<Tip>
  例で示しているクエリの多くは、出力をファイルに保存して `curl` で実行できます。

  ```bash theme={null}
  curl -XPOST "http://localhost:8123?default_format=RowBinary" \
    --data-binary "SELECT 42 :: UInt32"  > out.bin
  ```
</Tip>

その後、データはヘックスエディタで確認できます。

<div id="unsigned-leb128">
  ### 符号なし LEB128 (リトルエンディアン Base 128)
</div>

`String`、`Array`、`Map` などの可変サイズのデータ型の長さを符号化するために使われる、**符号なしリトルエンディアン**の可変長整数エンコーディングです。実装例は [LEB128 の Wikipedia ページ](https://en.wikipedia.org/wiki/LEB128#Decode_unsigned_integer)で確認できます。

<div id="integer-types">
  ### (U)Int8, (U)Int16, (U)Int32, (U)Int64, (U)Int128, (U)Int256
</div>

すべての整数型は、適切なバイト数で **リトルエンディアン** 形式にエンコードされます。符号付き型 (`Int8` から `Int256`) では、**2 の補数** 表現が使われます。ほとんどの言語では、組み込み機能または広く使われているライブラリを利用して、このような整数をバイト配列から取り出せます。大半の言語のネイティブな整数サイズを超える `Int128`/`Int256` および `UInt128`/`UInt256` については、独自にデシリアライズする必要がある場合があります。

<div id="bool">
  ### Bool
</div>

ブール値は1バイトでエンコードされ、`UInt8`と同様にデシリアライズできます。

* `0` は `false`
* `1` は `true`

<div id="float32-float64">
  ### Float32, Float64
</div>

**リトルエンディアン**形式の浮動小数点数で、`Float32` は4バイト、`Float64` は8バイトでエンコードされます。整数と同様、ほとんどの言語にはこれらの値を適切にデシリアライズするための手段が用意されています。

<div id="bfloat16">
  ### BFloat16
</div>

[BFloat16](/docs/ja/reference/data-types/float#bfloat16) (Brain Floating Point) は、Float32 と同じ範囲を持ちながら精度を抑えた 16 ビット浮動小数点フォーマットで、機械学習のワークロードに適しています。ワイヤ形式は、基本的に Float32 値の上位 16 ビットです。使用している言語がこれをネイティブでサポートしていない場合は、UInt16 として読み書きし、Float32 との間で相互変換するのが最も簡単です。

BFloat16 を Float32 に変換するには (疑似コード) :

```text theme={null}
// 2バイトをリトルエンディアンのUInt16として読み取る
// 16ビット左シフトしてFloat32のビット列を得る
bfloat16Bits = readUInt16()
float32Bits = bfloat16Bits << 16
floatValue = reinterpretAsFloat32(float32Bits)
```

Float32 を BFloat16 に変換するには (擬似コード) :

```text theme={null}
// Float32のビットを右に16ビットシフトしてBFloat16に切り詰める
float32Bits = reinterpretAsUInt32(floatValue)
bfloat16Bits = float32Bits >> 16
writeUInt16(bfloat16Bits)
```

`BFloat16` の内部値の例：

```sql theme={null}
SELECT CAST(1.25, 'BFloat16')
```

```text theme={null}
0xA0, 0x3F, // BFloat16 における 1.25
```

<div id="decimal">
  ### Decimal32, Decimal64, Decimal128, Decimal256
</div>

Decimal 型は、それぞれのビット幅に対応する**リトルエンディアン**の整数として表現されます。

* `Decimal32` - 4 バイト、つまり `Int32`
* `Decimal64` - 8 バイト、つまり `Int64`
* `Decimal128` - 16 バイト、つまり `Int128`
* `Decimal256` - 32 バイト、つまり `Int256`

Decimal 値をデシリアライズする際は、整数部と小数部を次の擬似コードで求められます。

```text theme={null}
let scale_multiplier = 10 ** scale
let whole_part = trunc(value / scale_multiplier)  // ゼロ方向に切り捨て
let fractional_part = value % scale_multiplier
let result = Decimal(whole_part, fractional_part)
```

ここで `trunc` は 0 に向かって切り捨てを行い (負の値では結果が異なる床除算ではなく) 、`scale` は小数点以下の桁数を表します。たとえば、`Decimal(10, 2)` (`Decimal32(2)` と同等) では、`scale` は `2` で、値 `12345` は `(123, 45)` として表現されます。

シリアライゼーションでは、この逆の操作が必要です：

```text theme={null}
let scale_multiplier = 10 ** scale
let result = whole_part * scale_multiplier + fractional_part
```

詳細は、[ClickHouseドキュメントのDecimal型](/docs/ja/reference/data-types/decimal)を参照してください。

<div id="string">
  ### String
</div>

ClickHouse の文字列は、**任意のバイト列**です。有効な UTF-8 である必要はありません。長さのプレフィックスは**バイト長**であり、文字数ではありません。

エンコードは次の 2 つの部分で構成されます。

1. 文字列の長さをバイト単位で示す可変長整数 (LEB128) 。
2. 文字列の生のバイト列。

たとえば、文字列 `foobar` は次のように *7* バイトでエンコードされます。

```text theme={null}
0x06, // 文字列のLEB128長 (6)
0x66, // 'f'
0x6f, // 'o'
0x6f, // 'o'
0x62, // 'b'
0x61, // 'a'
0x72, // 'r'
```

<div id="fixedstring">
  ### FixedString
</div>

`String` とは異なり、`FixedString` はスキーマで定義される固定長を持ちます。バイト列としてエンコードされ、値が `N` より短い場合は末尾がゼロバイトで埋められます。

<Note>
  `FixedString` を読み取る際、末尾のゼロバイトはパディングである場合も、データ中の実際の `\0` 文字である場合もあり、ワイヤ上では区別できません。ClickHouse 自体は `N` バイトをすべてそのまま保持します。
</Note>

空の `FixedString(3)` にはパディングのゼロだけが含まれます:

```text theme={null}
0x00, 0x00, 0x00
```

文字列 `hi` が入った空でない `FixedString(3)`:

```text theme={null}
0x68, // 'h'
0x69, // 'i'
0x00, // パディングゼロ
```

文字列 `bar` を含む、空でない `FixedString(3)`:

```text theme={null}
0x62, // 'b'
0x61, // 'a'
0x72, // 'r'
```

最後の例では、*3* バイトすべてを使用しているため、パディングは不要です。

<div id="date">
  ### Date
</div>

`1970-01-01` からの日数を表す `UInt16` (2 バイト) として格納されます。

サポートされる値の範囲: `[1970-01-01, 2149-06-06]`。

`Date` の内部値の例:

```sql theme={null}
SELECT CAST('2024-01-15', 'Date') AS d
```

```text theme={null}
0x19, 0x4D, // UInt16（リトルエンディアン）で19737 = 1970-01-01から19737日
```

<div id="date32">
  ### Date32
</div>

`1970-01-01` の***前後***の日数を表す `Int32` (4バイト) として格納されます。

対応する値の範囲: `[1900-01-01, 2299-12-31]`。

`Date32` の内部値の例:

```sql theme={null}
SELECT CAST('2024-01-15', 'Date32') AS d
```

```text theme={null}
0x19, 0x4D, 0x00, 0x00, // Int32（リトルエンディアン）で19737 = 1970-01-01から19737日
```

エポック以前の日時:

```sql theme={null}
SELECT CAST('1900-01-01', 'Date32') AS d
```

```text theme={null}
0x21, 0x9C, 0xFF, 0xFF, // -25567（Int32、リトルエンディアン）= 1970-01-01より25567日前
```

<div id="datetime">
  ### DateTime
</div>

`1970-01-01 00:00:00 UTC` ***からの*** 経過秒数を表す `UInt32` (4バイト) として格納されます。

構文:

```text theme={null}
DateTime([timezone])
```

たとえば、`DateTime` や `DateTime('UTC')` です。

<Note>
  バイナリ値は常に UTC エポックオフセットです。タイムゾーンによってエンコーディングが変わることはありません。ただし、文字列値が INSERT 時にどのように解釈されるかにはタイムゾーン **が** 影響します。つまり、`DateTime('America/New_York')` カラムに `'2024-01-15 10:30:00'` を挿入すると、同じ文字列を `DateTime('UTC')` カラムに挿入した場合とは異なるエポック値が保存されます。これは、その文字列がカラムのタイムゾーンにおける現地時刻として解釈されるためです。ワイヤ上では、どちらも単なる `UInt32` のエポック秒です。
</Note>

サポートされる値の範囲: `[1970-01-01 00:00:00, 2106-02-07 06:28:15]`。

`DateTime` の内部値の例:

```sql theme={null}
SELECT CAST('2024-01-15 10:30:00', 'DateTime(\'UTC\')') AS d
```

```text theme={null}
0x28, 0x09, 0xA5, 0x65, // 1705314600 をUInt32として（リトルエンディアン）
```

<div id="datetime64">
  ### DateTime64
</div>

`1970-01-01 00:00:00 UTC`を基準とした**ティック**数を表す`Int64` (8バイト) として格納されます。値はその***前後***のいずれも取り得ます。ティックの精度は`precision`パラメータで定義されます。以下の構文を参照してください。

```text theme={null}
DateTime64(precision, [timezone])
```

`precision` は `0` から `9` までの整数です。通常使われるのは、`3` (ミリ秒) 、`6` (マイクロ秒) 、
`9` (ナノ秒) のみです。

有効な DateTime64 定義の例: `DateTime64(0)`、`DateTime64(3)`、`DateTime64(6, 'UTC')`、`DateTime64(9, 'Europe/Amsterdam')`。

<Note>
  `DateTime` と同様に、バイナリ値は常に UTC エポックからのオフセットです。タイムゾーンは、INSERT 時に文字列値をどのように解釈するかに影響します ([DateTime](#datetime) の注記を参照) が、エンコード自体は常に UTC エポックからの `Int64` ティックです。
</Note>

`DateTime64` 型の基になる `Int64` 値は、UNIX エポックの前後における以下の単位数として解釈できます。

* `DateTime64(0)` - 秒。
* `DateTime64(3)` - ミリ秒。
* `DateTime64(6)` - マイクロ秒。
* `DateTime64(9)` - ナノ秒。

サポートされる値の範囲: `[0000-01-01 00:00:00, 9999-12-31 23:59:59.999999999]` (`precision` が 7 までの場合。`precision` 8 および 9 ではより狭くなります。詳細は以下の注記を参照してください)。

`DateTime64` の内部値の例:

* `DateTime64(3)`: 値 `1546300800000` は `2019-01-01 00:00:00 UTC` を表します。
* `DateTime64(6)`: 値 `1705314600123456` は `2024-01-15 10:30:00.123456 UTC` を表します。
* `DateTime64(9)`: 値 `1705314600123456789` は `2024-01-15 10:30:00.123456789 UTC` を表します。

<Note>
  基になる `Int64` ティックの範囲は精度が高くなるほど狭くなるため、サポートされる最大値も小さくなります。`precision` 8 では `4892-10-07`、`precision` 9 (ナノ秒) では UTC で `2262-04-11 23:47:16` です。
</Note>

<div id="time">
  ### Time
</div>

秒単位の時刻値を表す `Int32` として格納されます。負の値も有効です。

サポートされる値の範囲は `[-999:59:59, 999:59:59]` (つまり `[-3599999, 3599999]` 秒) です。

<Note>
  現時点では、`Time` または `Time64` を使用するには、設定 `enable_time_time64_type` を `1` に設定する必要があります。
</Note>

`Time` の内部値の例:

```sql theme={null}
SET enable_time_time64_type = 1;
SELECT CAST('15:32:16', 'Time') AS t
```

```text theme={null}
0x80, 0xDA, 0x00, 0x00, // 55936 Seconds = 15:32:16
```

<div id="time64">
  ### Time64
</div>

内部的には `Decimal64` (`Int64` として格納) で保存され、小数秒を含む時刻値を表します。精度は設定可能です。負の値も有効です。

構文:

```text theme={null}
Time64(precision)
```

ここで、`precision` は `0` から `9` までの整数です。一般的な値は、`3` (ミリ秒) 、`6` (マイクロ秒) 、`9` (ナノ秒) です。

サポートされる値の範囲は `[-999:59:59.xxxxxxxxx, 999:59:59.xxxxxxxxx]` です。

<Note>
  現時点では、`Time` または `Time64` を使用するには、設定 `enable_time_time64_type` を `1` に設定する必要があります。
</Note>

基になる `Int64` の値は、秒の小数部分を `10^precision` 倍した値を表します。

`Time64` の内部値の例:

```sql theme={null}
SET enable_time_time64_type = 1;
SELECT CAST('15:32:16.123456', 'Time64(6)') AS t
```

```text theme={null}
0x40, 0x82, 0x0D, 0x06,
0x0D, 0x00, 0x00, 0x00, // Int64としての55936123456
// 55936123456 / 10^6 = 55936.123456 Seconds = 15:32:16.123456
```

<div id="interval-types">
  ### インターバル型
</div>

すべてのインターバル型は `Int64` (8バイト、リトルエンディアン) として格納されます。値は、それぞれの時間単位の個数を表します。負の値も有効です。

インターバル型は次のとおりです: `IntervalNanosecond`、`IntervalMicrosecond`、`IntervalMillisecond`、`IntervalSecond`、`IntervalMinute`、`IntervalHour`、`IntervalDay`、`IntervalWeek`、`IntervalMonth`、`IntervalQuarter`、`IntervalYear`。

<Note>
  インターバルの型名 (例: `IntervalSecond` と `IntervalDay`) によって、格納される値の単位が決まります。ワイヤ形式でのエンコーディングは常に同じです。
</Note>

内部値の例:

```sql theme={null}
SELECT INTERVAL 5 SECOND   AS a,
     INTERVAL 10 DAY     AS b,
     INTERVAL -7 DAY     AS c,
     INTERVAL 3 YEAR     AS d,
     INTERVAL 500 MICROSECOND AS e
```

```text theme={null}
// IntervalSecond: 5
0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// IntervalDay: 10
0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// IntervalDay: -7
0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
// IntervalYear: 3
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// IntervalMicrosecond: 500
0xF4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
```

<div id="enum8-enum16">
  ### Enum8、Enum16
</div>

enum 定義内での enum 値のインデックスを表す 1 バイト (`Enum8` == `Int8`) または 2 バイト (`Enum16` == `Int16`) として格納されます。ストレージ型は **signed** である点に注意してください。つまり、enum 値には負の値も指定できます (例: `Enum8('a' = -128, 'b' = 0)`) 。

Enum は次のように簡単に定義できます。

```sql theme={null}
SELECT 1 :: Enum8('hello' = 1, 'world' = 2) AS e;
```

```text theme={null}
   ┌─e─────┐
1. │ hello │
   └───────┘
```

上で定義したEnum8は、クライアント側では次の値にマッピングされます。

```text theme={null}
Map<Int8, String> {
  1: 'hello',
  2: 'world'
}
```

あるいは、次のような、より複雑な方法もあります：

```sql theme={null}
SELECT 42 :: Enum16('f\'' = 1, 'x =' = 2, 'b\'\'' = 3, '\'c=4=' = 42, '4' = 1234) AS e;
```

```text theme={null}
   ┌─e─────┐
1. │ 'c=4= │
   └───────┘
```

上で定義した Enum16 は、クライアント側では次の値にマッピングされます:

```text theme={null}
Map<Int16, String> {
  1:    'f\'',
  2:    'x =',
  3:    'b\'',
  42:   '\'c=4=',
  1234: '4'
}
```

データ型パーサーにとっての主な課題は、`\'` のような `enum` 定義内のエスケープされた記号や、引用符で囲まれた文字列内に現れる可能性のある `=` のような特殊記号を正しく追跡することです。

<div id="uuid">
  ### UUID
</div>

16 バイトの並びとして表現されます。UUID は、**2 つのリトルエンディアン `UInt64` 値**として格納されます。標準的な UUID 表現の最初の 8 バイトはバイト順が逆になり、後半の 8 バイトもそれぞれ独立してバイト順が逆になります。

たとえば、UUID `61f0c404-5cb3-11e7-907b-a6006ad3dba0` の場合:

* 標準的なバイト表現: `61 f0 c4 04 5c b3 11 e7` | `90 7b a6 00 6a d3 db a0`
* 前半を逆順にしたもの (LE UInt64): `e7 11 b3 5c 04 c4 f0 61`
* 後半を逆順にしたもの (LE UInt64): `a0 db d3 6a 00 a6 7b 90`

`UUID` の内部値の例:

* `61f0c404-5cb3-11e7-907b-a6006ad3dba0` は次のように表現されます:

```text theme={null}
0xE7, 0x11, 0xB3, 0x5C, 0x04, 0xC4, 0xF0, 0x61,
0xA0, 0xDB, 0xD3, 0x6A, 0x00, 0xA6, 0x7B, 0x90,
```

* デフォルトの UUID `00000000-0000-0000-0000-000000000000` は、16 個のゼロバイトで表されます:

```text theme={null}
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
```

新しいレコードが挿入されたが、UUIDの値が指定されていない場合に使用できます。

<div id="ipv4">
  ### IPv4
</div>

4バイトの `UInt32` として、**リトルエンディアン** のバイト順で格納されます。これは、IP アドレスで一般的に使用される従来のネットワークバイトオーダー (ビッグエンディアン) とは異なる点に注意してください。`IPv4` の内部値の例:

```sql theme={null}
SELECT    
  CAST('0.0.0.0',         'IPv4') AS a,
  CAST('127.0.0.1',       'IPv4') AS b,
  CAST('192.168.0.1',     'IPv4') AS c,
  CAST('255.255.255.255', 'IPv4') AS d,
  CAST('168.212.226.204', 'IPv4') AS e
```

```text theme={null}
0x00, 0x00, 0x00, 0x00, // 0.0.0.0
0x01, 0x00, 0x00, 0x7f, // 127.0.0.1
0x01, 0x00, 0xa8, 0xc0, // 192.168.0.1
0xff, 0xff, 0xff, 0xff, // 255.255.255.255
0xcc, 0xe2, 0xd4, 0xa8, // 168.212.226.204
```

<div id="ipv6">
  ### IPv6
</div>

**ビッグエンディアン / ネットワークバイトオーダー** (MSB 先頭) で 16 バイトに格納されます。`IPv6` の内部値の例:

```sql theme={null}
SELECT
    CAST('2a02:aa08:e000:3100::2',        'IPv6') AS a,
    CAST('2001:44c8:129:2632:33:0:252:2', 'IPv6') AS b,
    CAST('2a02:e980:1e::1',               'IPv6') AS c
```

```text theme={null}
// 2a02:aa08:e000:3100::2
0x2A, 0x02, 0xAA, 0x08, 0xE0, 0x00, 0x31, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
// 2001:44c8:129:2632:33:0:252:2
0x20, 0x01, 0x44, 0xC8, 0x01, 0x29, 0x26, 0x32, 
0x00, 0x33, 0x00, 0x00, 0x02, 0x52, 0x00, 0x02,
// 2a02:e980:1e::1
0x2A, 0x02, 0xE9, 0x80, 0x00, 0x1E, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
```

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

Nullable データ型は、次のようにエンコードされます。

1. 値が `NULL` かどうかを示す 1 バイト:
   * `0x00` は、値が `NULL` ではないことを示します。
   * `0x01` は、値が `NULL` であることを示します。
2. 値が `NULL` でない場合は、基になるデータ型が通常どおりエンコードされます。値が `NULL` の場合、基になる型については **追加のバイトは一切** 書き込まれません。

たとえば、`Nullable(UInt32)` 型の値:

```sql theme={null}
SELECT    
   CAST(42,   'Nullable(UInt32)') AS a,
   CAST(NULL, 'Nullable(UInt32)') AS b
```

```text theme={null}
0x00,                   // NULLではない - 値が続く
0x2A, 0x00, 0x00, 0x00, // UInt32(42)
0x01,                   // NULL - 後続データなし
```

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

RowBinary フォーマットでは、low-cardinality マーカーはワイヤ形式に影響しません。たとえば、`LowCardinality(String)` は通常の `String` と同じようにエンコードされます。

<Warning>
  これは RowBinary にのみ当てはまります。Native format では、`LowCardinality` は Dictionary ベースの別のエンコードを使用します。
</Warning>

<Note>
  カラムは `LowCardinality(Nullable(T))` として定義できますが、`Nullable(LowCardinality(T))` として定義することはできません。常に server から error になります。
</Note>

テスト時には、カバレッジを広げるために、[allow\_suspicious\_low\_cardinality\_types](/docs/ja/reference/settings/session-settings#allow_suspicious_low_cardinality_types) を `1` に設定すると、`LowCardinality` 内でほとんどの data types を許可できます。

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

Array は次のようにエンコードされます。

1. 配列の要素数を示す [可変長整数 (LEB128) ](#unsigned-leb128)
2. 配列の各要素。基になるデータ型と同じ方法でエンコードされます。

たとえば、`UInt32` 型の値を持つ配列は次のとおりです。

```sql theme={null}
SELECT CAST(array(1, 2, 3), 'Array(UInt32)') AS arr
```

```text theme={null}
0x03,                   // LEB128 - Arrayの要素数は3
0x01, 0x00, 0x00, 0x00, // UInt32(1)
0x02, 0x00, 0x00, 0x00, // UInt32(2)
0x03, 0x00, 0x00, 0x00, // UInt32(3)
```

やや複雑な例:

```sql theme={null}
SELECT array('foobar', 'qaz') AS arr
```

```text theme={null}
0x02,             // LEB128 - 配列の要素数は2
0x06,             // LEB128 - 1番目の文字列は6バイト
0x66, 0x6f, 0x6f, 
0x62, 0x61, 0x72, // 'foobar'
0x03,             // LEB128 - 2番目の文字列は3バイト
0x71, 0x61, 0x7a, // 'qaz'
```

<Note>
  Array には Nullable な値を含めることができますが、Array 自体を Nullable にすることはできません。
</Note>

以下は有効です。

```sql theme={null}
SELECT CAST([NULL, 'foo'], 'Array(Nullable(String))') AS arr;
```

```text theme={null}
   ┌─arr──────────┐
1. │ [NULL,'foo'] │
   └──────────────┘
```

そして、次のようにエンコードされます。

```text theme={null}
0x02,             // LEB128  - 配列には2つの要素がある
0x01,             // NULLである - この要素に続くデータはない
0x00,             // NULLでない - データが続く
0x03,             // LEB128  - 文字列は3バイト
0x66, 0x6f, 0x6f, // 'foo'
```

多次元配列の扱いの例は、[Geo セクション](#geo-types)に記載されています。

<div id="tuple">
  ### Tuple
</div>

タプルは、追加のメタ情報や区切り文字を使わず、各要素をそれぞれ対応するワイヤ形式で順に並べてエンコードされます。

```sql theme={null}
CREATE OR REPLACE TABLE foo
(
    `t` Tuple(
           UInt32,
           String,
           Array(UInt8)
        )
)
ENGINE = Memory;
INSERT INTO foo VALUES ((42, 'foo', array(99, 144)));
```

```text theme={null}
0x2a, 0x00, 0x00, 0x00, // UInt32 として 42
0x03,                   // LEB128 - 文字列は 3 バイト
0x66, 0x6f, 0x6f,       // 'foo'
0x02,                   // LEB128 - 配列は 2 要素
0x63,                   // UInt8 として 99
0x90,                   // UInt8 として 144
```

Tuple データ型の文字列エンコーディングでは、エスケープされた記号や特殊文字を追跡する必要があるなど、[Enum 型](#enum8-enum16)と同様の課題があります。さらに、Tuple では開き括弧と閉じ括弧も追跡する必要があります。加えて、複雑な Tuple には、ネストされた別の Tuple、Array、Map、さらには enum が含まれることもある点に注意してください。

たとえば次の表では、Tuple に名前の中にバッククォートと括弧を含む enum が含まれており、適切に処理しないとパースの問題を引き起こす可能性があります。

```sql theme={null}
CREATE OR REPLACE TABLE foo
(
   `t` Tuple(
          Enum8('f\'()' = 0),
          Array(Nullable(Tuple(UInt32, String)))
       )
) ENGINE = Memory;
```

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

map は `Array(Tuple(K, V))` とみなすことができ、ここで `K` はキーの型、`V` は値の型です。map は次のようにエンコードされます。

1. map 内の要素数を示す [可変長整数 (LEB128)](#unsigned-leb128)。
2. map の各要素を、対応する型でエンコードされたキー・バリューのペアとして格納します。

たとえば、キーが `String`、値が `UInt32` の map は次のとおりです。

```sql theme={null}
SELECT CAST(map('foo', 1, 'bar', 2), 'Map(String, UInt32)') AS m
```

```text theme={null}
0x02,                   // LEB128 - マップの要素数は2
0x03,                   // LEB128 - 最初のキーは3バイト
0x66, 0x6f, 0x6f,       // 'foo'
0x01, 0x00, 0x00, 0x00, // UInt32(1)
0x03,                   // LEB128 - 2番目のキーは3バイト
0x62, 0x61, 0x72,       // 'bar'
0x02, 0x00, 0x00, 0x00, // UInt32(2)
```

<Note>
  `Map(String, Map(Int32, Array(Nullable(String))))` のように、深くネストされた構造を持つ Map も可能で、その場合も上記と同様にエンコードされます。
</Note>

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

この型は、ほかのデータ型のユニオンを表します。型 `Variant(T1, T2, ..., TN)` は、この型の各行が `T1`、`T2`、…、`TN` のいずれかの型、またはそのどれにも該当しない値 (`NULL` 値) を持つことを意味します。

<Warning>
  エンドユーザーにとっては `Variant(T1, T2)` と `Variant(T2, T1)` はまったく同じ意味ですが、ワイヤ形式では定義内の型の順序が重要です。定義内の型は常にアルファベット順にソートされます。これは、どのバリアントかが "判別子"、つまり定義内のデータ型の索引によってエンコードされるためです。
</Warning>

次の例を見てみましょう。

```sql theme={null}
SET allow_experimental_variant_type = 1,
    allow_suspicious_variant_types = 1;
CREATE OR REPLACE TABLE foo
(
  -- ユーザー入力での型の順序は関係ない。
  -- 型はワイヤ形式では常にアルファベット順にソートされる。
  `var` Variant(
           Array(Int16),
           Bool,
           Date,
           FixedString(6),
           Float32, Float64,
           Int128, Int16, Int32, Int64, Int8,
           String,
           UInt128, UInt16, UInt32, UInt64, UInt8
       )
)
ENGINE = MergeTree
ORDER BY ();
INSERT INTO foo VALUES (true), ('foobar' :: FixedString(6)), (100.5 :: Float64), (100 :: Int128), ([1, 2, 3] :: Array(Int16));
SELECT * FROM foo FORMAT RowBinary;
```

```text theme={null}
0x01,                               // 型インデックス -> Bool
 0x01,                               // true
 0x03,                               // 型インデックス -> FixedString(6)
 0x66, 0x6F, 0x6F, 0x62, 0x61, 0x72, // 'foobar' 
 0x05,                               // 型インデックス -> Float64
 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x20, 0x59, 0x40,             // Float64 としての 100.5
 0x06,                               // 型インデックス -> Int128
 0x64, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00,             // Int128 としての 100
 0x00,                               // 型インデックス -> Array(Int16)
 0x03,                               // LEB128 - 配列の要素数は 3
 0x01, 0x00,                         // Int16 としての 1
 0x02, 0x00,                         // Int16 としての 2
 0x03, 0x00,                         // Int16 としての 3
```

`NULL` 値は、判別子バイト `0xFF` でエンコードされます:

```sql theme={null}
SELECT NULL :: Variant(UInt32, String)
```

```text theme={null}
0xFF, // discriminant = NULL
```

[allow\_suspicious\_variant\_types](/docs/ja/reference/settings/session-settings#allow_suspicious_variant_types) 設定を使用すると、`Variant` 型をより網羅的にテストできます。

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

`Dynamic` 型は、実行時に決まる任意の型の値を保持できます。RowBinary フォーマットでは、各値は自己記述的です。最初の部分には、[このフォーマット](/docs/ja/reference/data-types/data-types-binary-encoding)で表される型指定が入ります。続いて、このドキュメントで説明している値エンコードに従った内容が続きます。したがって、値をパースするには、型の索引を使って適切なパーサーを判断し、あとはすでに別の場所で使っている RowBinary のパース処理を再利用するだけです。

```text theme={null}
[BinaryTypeIndex][type-specific parameters...][value]
```

ここで、`BinaryTypeIndex` は型を識別する 1 バイトの値です。型インデックスとパラメータについては、[こちら](/docs/ja/reference/data-types/data-types-binary-encoding) のリファレンスを参照してください。

`NULL` の Dynamic 値は、`BinaryTypeIndex` `0x00` (`Nothing` 型) としてエンコードされ、追加のバイトはありません:

```sql theme={null}
SELECT NULL::Dynamic
```

```text theme={null}
00                        # BinaryTypeIndex: Nothing (0x00)、NULLを表す
```

**例:**

```sql theme={null}
SELECT 42::Dynamic
```

```text theme={null}
0a                        # BinaryTypeIndex: Int64 (0x0A)
2a 00 00 00 00 00 00 00   # Int64 value: 42
```

```sql theme={null}
SELECT toDateTime64('2024-01-15 10:30:00', 3, 'America/New_York')::Dynamic
```

```text theme={null}
14                        # BinaryTypeIndex: DateTime64WithTimezone (0x14)
03                        # UInt8: 精度
10                        # VarUInt: タイムゾーン名の長さ
41 6d 65 72 69 63 61 2f   # "America/"
4e 65 77 5f 59 6f 72 6b   # "New_York"
c0 6c be 0d 8d 01 00 00   # Int64: timestamps
```

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

JSON型はデータを2つの異なるカテゴリにエンコードします：

1. **型付きパス** - スキーマ内で型を明示して宣言されたパス (例: `JSON(user_id UInt32, name String)`)
2. **動的パス/動的パスの上限を超えた場合のオーバーフローパス** - `Dynamic` 型として保存される実行時検出パス。値のエンコーディングの前に型定義が付きます。

この2つのカテゴリでは、ワイヤ形式とルールが異なります。

| パスのカテゴリ   | シリアライゼーションに含まれるか     | 値のエンコーディング | Variant/Nullable を使用可能か |
| --------- | -------------------- | ---------- | ----------------------- |
| **型付きパス** | 常に含まれる (NULL の場合も含む) | 型固有のバイナリ形式 | はい                      |
| **動的パス**  | NULL でない場合のみ         | 動的         | いいえ                     |

パスは3つのグループに分けてシリアライズされ、typed paths、dynamic paths、shared data (オーバーフロー) pathsの順に書き込まれます。typed pathsとdynamic pathsは実装定義の順序 (内部ハッシュマップのイテレーションによって決定) で書き込まれ、shared data pathsはアルファベット順で書き込まれます。読み取り側は特定のパス順序に依存しないでください。デシリアライザは各パスを位置ではなく名前によってディスパッチします。

RowBinary フォーマットにおける各 JSON 行は、次のようにシリアライズされます：

```text theme={null}
[VarUInt: number_of_paths]
[String: path_1][value_1]
[String: path_2][value_2]
...
```

**例：**

**1. 型付きパスのみを含むシンプルなJSON：**

スキーマ: `JSON(user_id UInt32, active Bool)`

行: `{"user_id": 42, "active": true}`

バイナリエンコーディング (注釈付き16進数) ：

```text theme={null}
02                              # VarUInt: 合計2パス

# 型付きパス "active"
06 61 63 74 69 76 65            # String: "active" (長さ6 + バイト列)
01                              # Bool/UInt8 値: true (1)

# 型付きパス "user_id"
07 75 73 65 72 5F 69 64         # String: "user_id" (長さ7 + バイト列)
2A 00 00 00                     # UInt32 値: 42 (リトルエンディアン)
```

**2. 型付きパスと動的パスを持つシンプルなJSON：**

スキーマ: `JSON(user_id UInt32, active Bool)`

行: `{"user_id": 42, "active": true, "name": "Alice"}`

バイナリエンコーディング (注釈付き16進数) ：

```text theme={null}
03                              # VarUInt: 合計3パス

# 型付きパス "active"
06 61 63 74 69 76 65            # String: "active" (長さ6 + バイト列)
01                              # Bool/UInt8 値: true (1)

# 動的パス "name"
04 6E 61 6D 65                  # String: "name" (長さ4 + バイト列)
15                              # BinaryTypeIndex: String (0x15)
05 41 6C 69 63 65               # String 値: "Alice" (長さ5 + バイト列)

# 型付きパス "user_id"
07 75 73 65 72 5F 69 64         # String: "user_id" (長さ7 + バイト列)
2A 00 00 00                     # UInt32 値: 42 (little-endian)
```

**3. NULLの処理:**

型付きNullableカラムの場合、nullが返されます：

スキーマ: `JSON(score Nullable(Int32))`

行: `{"score": null }`

バイナリエンコーディング (注釈付き16進数) ：

```text theme={null}
01                              # VarUInt: パス合計1件

# 型付きパス "score" (Nullable)
05 73 63 6f 72 65               # String: "score" (長さ5 + バイト列)
01                              # Nullableフラグ: 1 (NULLのため、後続の値なし)
```

型付き非Nullableカラムの場合、デフォルト値が返されます：

Schema: `JSON(name String)`

行: `{"name": null}`

バイナリエンコーディング:

```text theme={null}
01                              # VarUInt: 1 path（動的なNULLパスはスキップされます！）

04 6e 61 6d 65  # "name"
00              # String の長さ 0（空文字列）
```

動的パスの場合、これは無視されます：

スキーマ: `JSON(id UInt64)`

行: `{"id": 100, "metadata": null}`

バイナリエンコーディング:

```text theme={null}
01                              # VarUInt: パス1個（動的NULLパスはスキップされます！）

# 型付きパス "id"
02 69 64                        # String: "id" (length 2 + bytes)
64 00 00 00 00 00 00 00         # UInt64 値: 100（little-endian）
```

注意: NULL 値を持つ `metadata` パスは、動的パスが非 null の場合にのみシリアライズされるため、**含まれません**。これは型付きパスとの重要な相違点です。

**4. ネストされたJSONオブジェクト：**

スキーマ: `JSON()`

行: `{"user": {"name": "Bob", "age": 30}}`

バイナリエンコーディング (注釈付き16進表記) :

```text theme={null}
02                              # VarUInt: パス数 2（ネストされたオブジェクトはフラット化される）

# 動的パス "user.age"
08 75 73 65 72 2E 61 67 65      # String: "user.age"（長さ 8 + バイト列）
0A                              # BinaryTypeIndex: Int64（0x0A）
1E 00 00 00 00 00 00 00         # Int64 値: 30（リトルエンディアン）

# 動的パス "user.name"
09 75 73 65 72 2E 6E 61 6D 65   # String: "user.name"（長さ 9 + バイト列）
15                              # BinaryTypeIndex: String（0x15）
03 42 6F 62                     # String 値: "Bob"（長さ 3 + バイト列）

```

注: ネストされたオブジェクトは、ネスト構造ではなくドット区切りのパスにフラット化されます (例: `user.name`) 。

**代替: JSONをStringとして扱うモード**

設定 `output_format_binary_write_json_as_string=1` を有効にすると、JSONカラムは構造化されたバイナリフォーマットではなく、1つのJSONテキスト文字列としてシリアライズされます。JSONカラムへの書き込みには、対応する設定 `input_format_binary_read_json_as_string` もあります。ここでどちらの設定を使うかは、JSONをクライアント側でパースするか、サーバー側でパースするかによって決まります。

<div id="geo-types">
  ### Geo 型
</div>

Geo は、地理データを表現するデータ型のカテゴリです。次の型が含まれます。

* `Point` - `Tuple(Float64, Float64)` として表されます。
* `Ring` - `Array(Point)` または `Array(Tuple(Float64, Float64))` として表されます。
* `Polygon` - `Array(Ring)` または `Array(Array(Tuple(Float64, Float64)))` として表されます。
* `MultiPolygon` - `Array(Polygon)` または `Array(Array(Array(Tuple(Float64, Float64))))` として表されます。
* `LineString` - `Array(Point)` または `Array(Tuple(Float64, Float64))` として表されます。
* `MultiLineString` - `Array(LineString)` または `Array(Array(Tuple(Float64, Float64)))` として表されます。

Geo の値のワイヤ形式は、Tuple および Array の場合とまったく同じです。`RowBinaryWithNamesAndTypes` フォーマットのヘッダーには、これらの型の別名 (たとえば `Point`、`Ring`、`Polygon`、`MultiPolygon`、`LineString`、`MultiLineString`) が含まれます。

```sql theme={null}
SELECT    (1.0, 2.0)                                       :: Point           AS point,
    [(3.0, 4.0), (5.0, 6.0)]                         :: Ring            AS ring,
    [[(7.0, 8.0), (9.0, 10.0)], [(11.0, 12.0)]]      :: Polygon         AS polygon,
    [[[(13.0, 14.0), (15.0, 16.0)], [(17.0, 18.0)]]] :: MultiPolygon    AS multi_polygon,
    [(19.0, 20.0), (21.0, 22.0)]                     :: LineString      AS line_string,
    [[(23.0, 24.0), (25.0, 26.0)], [(27.0, 28.0)]]   :: MultiLineString AS multi_line_string
```

```text theme={null}
// Point - または Tuple(Float64, Float64)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, // Point.X
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, // Point.Y
// Ring - または Array(Tuple(Float64, Float64))
0x02, // LEB128 - "ring" 配列には 2 点が含まれる
   // Ring - 点 #1
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 
   // Ring - 点 #2
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40, 
// Polygon - または Array(Array(Tuple(Float64, Float64)))
0x02, // LEB128 - "polygon" 配列には 2 つの Ring が含まれる
   0x02, // LEB128 - 最初の Ring には 2 点が含まれる
      // Polygon - Ring #1 - 点 #1
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x40, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40,
      // Polygon - Ring #1 - 点 #2
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x40, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 
  0x01, // LEB128 - 2 番目の Ring には 1 点が含まれる
      // Polygon - Ring #2 - 点 #1 (唯一の点)
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x40, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x40, 
// MultiPolygon - または Array(Array(Array(Tuple(Float64, Float64))))
0x01, // LEB128 - "multi_polygon" 配列には 1 つの Polygon が含まれる
   0x02, // LEB128 - 最初の Polygon には 2 つの Ring が含まれる
      0x02, // LEB128 - 最初の Ring には 2 点が含まれる
         // MultiPolygon - Polygon #1 - Ring #1 - 点 #1
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x40, 
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x40,
         // MultiPolygon - Polygon #1 - Ring #1 - 点 #2
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x40, 
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x40, 
      0x01, // LEB128 - 2 番目の Ring には 1 点が含まれる
        // MultiPolygon - Polygon #1 - Ring #2 - 点 #1 (唯一の点)
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x40, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x40, 
 // LineString - または Array(Tuple(Float64, Float64))
 0x02, // LEB128 - LineString には 2 点が含まれる
    // LineString - 点 #1
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x40, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40,
    // LineString - 点 #2
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x40, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x40, 
 // MultiLineString - または Array(Array(Tuple(Float64, Float64)))
 0x02, // LEB128 - MultiLineString には 2 つの LineString が含まれる
   0x02, // LEB128 - 最初の LineString には 2 点が含まれる
     // MultiLineString - LineString #1 - 点 #1
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x40, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x40, 
     // MultiLineString - LineString #1 - 点 #2
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x40, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x40, 
   0x01, // LEB128 - 2 番目の LineString には 1 点が含まれる
     // MultiLineString - LineString #2 - 点 #1 (唯一の点)
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x40, 
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x40,
```

<div id="geometry">
  ### Geometry
</div>

`Geometry` は、上記に挙げた任意の Geo 型を保持できる `Variant` 型です。ワイヤ上では `Variant` とまったく同じようにエンコードされ、後続する Geo 型を示す 判別子 バイトが付加されます。

Geometry の 判別子 インデックスは次のとおりです。

| インデックス | 型               |
| ------ | --------------- |
| 0      | LineString      |
| 1      | MultiLineString |
| 2      | MultiPolygon    |
| 3      | Point           |
| 4      | Polygon         |
| 5      | Ring            |

ワイヤ形式の構造:

```text theme={null}
// 1バイトのdiscriminant（0〜5）
// 続いて対応するGeoタイプのデータ
```

`Point` を `Geometry` としてエンコードした例:

```sql theme={null}
SELECT ((1.0, 2.0)::Point)::Geometry
```

```text theme={null}
0x03,                                           // 判別子 = 3 (Point)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, // Point.X = 1.0 (Float64)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, // Point.Y = 2.0 (Float64)
```

`Ring` を `Geometry` としてエンコードした例:

```text theme={null}
0x05,       // 判別子 = 5 (Ring)
0x02,       // LEB128 - Arrayは2点を持つ
// Point #1
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, // X = 3.0
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, // Y = 4.0
// Point #2
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x40, // X = 5.0
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40, // Y = 6.0
```

<div id="nested">
  ### Nested
</div>

`Nested` のワイヤ形式は、`flatten_nested` 設定に依存します。

<Warning>
  1 行内のすべての部分配列は、**同じ長さである必要があります**。これはサーバー側で強制される制約です。長さが一致しない場合、挿入時にエラーが発生します。
</Warning>

<div id="nested-flattened">
  #### `flatten_nested = 1` (デフォルト)
</div>

デフォルト設定では、`Nested` は独立した配列にフラット化されます。各サブカラムは、ドット区切りの名前を持つ個別の `Array` カラムになります。

```sql theme={null}
CREATE OR REPLACE TABLE foo
(
    n Nested(a String, b Int32)
) ENGINE = MergeTree ORDER BY ();
-- flatten_nested=1 はデフォルト値
INSERT INTO foo VALUES (['foo', 'bar'], [42, 144]);
```

`DESCRIBE TABLE foo` を実行すると、フラット化されたカラムが表示されます。

```text theme={null}
   ┌─name─┬─type──────────┐
1. │ n.a  │ Array(String) │
2. │ n.b  │ Array(Int32)  │
   └──────┴───────────────┘
```

各配列は、[Array](#array) セクションで説明しているとおり、それぞれ独立してシリアライズされます。

```text theme={null}
0x02,                   // LEB128 - 最初の配列 (n.a) の String 要素数は 2
 0x03,                   // LEB128 - 最初の文字列は 3 バイト
 0x66, 0x6F, 0x6F,       // 'foo'
 0x03,                   // LEB128 - 2 番目の文字列は 3 バイト
 0x62, 0x61, 0x72,       // 'bar'
0x02,                   // LEB128 - 2 番目の配列 (n.b) の Int32 要素数は 2
 0x2A, 0x00, 0x00, 0x00, // Int32 としての 42
 0x90, 0x00, 0x00, 0x00, // Int32 としての 144
```

<div id="nested-unflattened">
  #### `flatten_nested = 0`
</div>

`flatten_nested = 0` の場合、`Nested` は `Array(Tuple(...))` 型の単一のカラムとして保持されます。カラム名はドット区切りではありません。

```sql theme={null}
SET flatten_nested = 0;
CREATE OR REPLACE TABLE foo
(
    n Nested(a String, b Int32)
) ENGINE = MergeTree ORDER BY ();
INSERT INTO foo VALUES ([('foo', 42), ('bar', 144)]);
```

`DESCRIBE TABLE foo` では、1 つのカラムが表示されます。

```text theme={null}
   ┌─name─┬─type───────────────────────┐
1. │ n    │ Nested(a String, b Int32)  │
   └──────┴────────────────────────────┘
```

エンコーディングは `Array(Tuple(String, Int32))` です。最初に配列長のプレフィックスがあり、続いて各要素のタプルのフィールドが順に並びます。

```text theme={null}
0x02,                   // LEB128 - 配列の要素数: 2
 0x03,                   // LEB128 - 1番目のタプル、フィールド a: 3バイト
 0x66, 0x6F, 0x6F,       // 'foo'
 0x2A, 0x00, 0x00, 0x00, // 1番目のタプル、フィールド b: Int32 として 42
 0x03,                   // LEB128 - 2番目のタプル、フィールド a: 3バイト
 0x62, 0x61, 0x72,       // 'bar'
 0x90, 0x00, 0x00, 0x00, // 2番目のタプル、フィールド b: Int32 として 144
```

フィールドが、フラット化された表現のようにカラムごとにまとめられている (a₁, a₂, b₁, b₂) のではなく、要素ごとに交互に並んでいる (a₁, b₁, a₂, b₂) ことに注目してください。

<div id="simpleaggregatefunction">
  ### SimpleAggregateFunction
</div>

`SimpleAggregateFunction(func, T)` は、基になるデータ型 `T` と同一の形式でエンコードされます。集約関数名はワイヤ形式に影響しません。

たとえば、`SimpleAggregateFunction(max, UInt32)` は通常の `UInt32` と同じ形式でエンコードされます。

```sql theme={null}
CREATE TABLE test_saf
(
    key UInt32,
    val SimpleAggregateFunction(max, UInt32)
) ENGINE = AggregatingMergeTree ORDER BY key;

INSERT INTO test_saf VALUES (1, 42);
SELECT val FROM test_saf;
```

RowBinaryWithNamesAndTypes のヘッダーでは型は `SimpleAggregateFunction(max, UInt32)` と示されますが、実際にワイヤ上で流れる値は単なる `UInt32` です:

```text theme={null}
0x2A, 0x00, 0x00, 0x00, // UInt32 として 42
```

<div id="aggregatefunction">
  ### AggregateFunction
</div>

`AggregateFunction(func, T)` は、aggregate function の完全な中間状態を格納します。中間状態を格納する点は同じでも、それを基になるデータ型と同じ形式でエンコードする `SimpleAggregateFunction` とは異なり、`AggregateFunction` は各 aggregate function 固有のフォーマットを持つ不透明なバイナリブロブを格納します。

<Warning>
  aggregate states には、RowBinary フォーマットでは**長さプレフィックスがありません**。そのため、何バイト読み取るべきかを判断するには、パーサーが各 aggregate function 固有の内部シリアライゼーションフォーマットを理解している必要があります。実際には、ほとんどのクライアントは aggregate states を不透明なものとして扱い、シリアライゼーションは server に任せるため、`*State` / `*Merge` コンビネーターを使用します。
</Warning>

内部フォーマットは関数ごとに異なります。簡単な例をいくつか示します。

**`countState`** — カウントを VarUInt (LEB128) として格納します。

```sql theme={null}
SELECT countState(number) FROM numbers(5)
```

```text theme={null}
0x05, // VarUInt: 5
```

**`sumState`** — 累積された合計を固定サイズの整数に格納します。ビット幅は引数の型に依存します (整数型の引数の場合は `UInt64`) :

```sql theme={null}
SELECT sumState(toUInt32(number)) FROM numbers(5) -- 合計 = 0+1+2+3+4 = 10
```

```text theme={null}
0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // UInt64として10
```

**`minState` / `maxState`** — フラグバイトに続けて、基になる型の値を格納します。フラグは、空の状態 (値が1つもない) の場合は `0x00`、値がある場合は `0x01` です:

```sql theme={null}
SELECT maxState(toUInt32(number)) FROM numbers(5) -- 最大値 = 4
```

```text theme={null}
0x01,                   // フラグ: 値あり
0x04, 0x00, 0x00, 0x00, // UInt32 としての 4
```

空の状態 (集計された行がない) :

```sql theme={null}
SELECT minState(toUInt32(number)) FROM numbers(0)
```

```text theme={null}
0x00, // フラグ: 値なし
```

<Note>
  `uniq`、`quantile`、`groupArray` のようなより複雑な関数では、実装固有のフォーマットが使用されます。これらの状態を読み書きする必要がある場合は、該当する関数の ClickHouse ソースコードを参照してください。
</Note>

<div id="qbit">
  ### QBit
</div>

`QBit` は、異なる精度レベルで効率的にルックアップできるベクトル型です。内部的には転置フォーマットで保存されます。転送時には、QBit は単に基底要素型 (`Int8`、`Float32`、`Float64`、または `BFloat16`) の `Array` です。保存時のビット転置の最適化は RowBinary プロトコルではなく、サーバー側で行われます。

構文:

```text theme={null}
QBit(element_type, dimension[, stride])
```

ここで、`element_type` は `Int8`、`Float32`、`Float64`、または `BFloat16` で、`dimension` は固定のベクトル次元です。省略可能な `stride` は、サーバー側でビットプレーンを保存ストリームにどうグループ化するかだけを制御するもので、RowBinary のワイヤ形式には影響しません。ワイヤ形式は常に `dimension` 個の要素からなる完全な配列です。

ワイヤ形式: `Array(element_type)` と同一です。

```text theme={null}
// LEB128 length
// followed by `length` elements of `element_type`
```

`[1.0, 2.0, 3.0, 4.0]` を含む `QBit(Float32, 4)` のエンコード例:

```sql theme={null}
SELECT [1.0, 2.0, 3.0, 4.0]::QBit(Float32, 4)
```

```text theme={null}
0x04,                   // LEB128 - array has 4 elements
0x00, 0x00, 0x80, 0x3F, // 1.0 as Float32
0x00, 0x00, 0x00, 0x40, // 2.0 as Float32
0x00, 0x00, 0x40, 0x40, // 3.0 as Float32
0x00, 0x00, 0x80, 0x40, // 4.0 as Float32
```

<div id="format-settings">
  ## フォーマット設定
</div>

以下の設定は、すべての `RowBinary` 系フォーマットに共通です。

| 設定                                                                                                                                       | 説明                                                                                                                                                                                                                 | デフォルト   |
| ---------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- |
| [`format_binary_max_string_size`](/docs/ja/reference/settings/formats#format_binary_max_string_size)                                          | RowBinary フォーマットで許可される String の最大サイズです。                                                                                                                                                                            | `1GiB`  |
| [`output_format_binary_encode_types_in_binary_format`](/docs/ja/reference/settings/formats#input_format_binary_decode_types_in_binary_format) | [`RowBinaryWithNamesAndTypes`](/docs/ja/reference/formats/RowBinary/RowBinaryWithNamesAndTypes) 出力フォーマットで、ヘッダー内の型を、型名の文字列ではなく [`binary encoding`](/docs/ja/reference/data-types/data-types-binary-encoding) を使って書き込めるようにします。 | `false` |
| [`input_format_binary_decode_types_in_binary_format`](/docs/ja/reference/settings/formats#input_format_binary_decode_types_in_binary_format)  | [`RowBinaryWithNamesAndTypes`](/docs/ja/reference/formats/RowBinary/RowBinaryWithNamesAndTypes) 入力フォーマットで、ヘッダー内の型を、型名の文字列ではなく [`binary encoding`](/docs/ja/reference/data-types/data-types-binary-encoding) を使って読み取れるようにします。 | `false` |
| [`output_format_binary_write_json_as_string`](/docs/ja/reference/settings/formats#output_format_binary_write_json_as_string)                  | [`RowBinary`](/docs/ja/reference/formats/RowBinary/RowBinary) 出力フォーマットで、[`JSON`](/docs/ja/reference/data-types/newjson) データ型の値を `JSON` [String](/docs/ja/reference/data-types/string) 値として書き込めるようにします。                            | `false` |
| [`input_format_binary_read_json_as_string`](/docs/ja/reference/settings/formats#input_format_binary_read_json_as_string)                      | [`RowBinary`](/docs/ja/reference/formats/RowBinary/RowBinary) 入力フォーマットで、[`JSON`](/docs/ja/reference/data-types/newjson) データ型の値を `JSON` [String](/docs/ja/reference/data-types/string) 値として読み取れるようにします。                            | `false` |
