| 入力 | 出力 | 別名 |
|---|---|---|
| ✔ | ✔ |
説明
Native フォーマットは、カラムを行に変換しない真の「列指向」フォーマットであるため、ClickHouse で最も効率的なフォーマットです。
このフォーマットでは、データはバイナリフォーマットで ブロック 単位に読み書きされます。
各ブロックについて、行数、カラム数、カラム名と型、さらにブロック内の各カラムのデータ部分が順に記録されます。
これは、サーバー間のやり取りに使われるネイティブインターフェイス、コマンドラインクライアント、C++ クライアントで使用されるフォーマットです。
データ型のワイヤ形式
ネイティブ TCP バイナリプロトコルを使用する場合 (または HTTP エンドポイントが
?client_protocol_version=<n> を受信する場合) 、
カラム数と行数の前に BlockInfo 構造体が書き込まれます。このセクションの例では、
プロトコルバージョンを指定しない通常の HTTP インターフェイスを使用しているため、BlockInfo は省略されます。ブロック構造
number と str の 2 つのカラムを持つ 3 行を返します:
複数のブロック
単純なデータ型
RowBinary/RowBinaryWithNamesAndTypes と似ています。
この説明に該当する型の一覧は次のとおりです。
- (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
複合データ型
RowBinary および RowBinaryWithNamesAndTypes のものとは異なります。
- Nullable
- LowCardinality
- Array
- Map
- Variant
- Dynamic
- JSON
Nullable
Nativeフォーマットでは、Nullableカラムでは実際のデータの前に、ブロック内の行数と同じだけのバイト列が置かれます。各バイトは、その値が NULL かどうかを示します。たとえば、このクエリでは、代わりに各奇数が NULL になります。
Nullable(String) でも同様です。null インジケーターは常に nullable のマスクバイトで決まり、
マスク値が 0x01 の場合は、文字列の内容に関係なくその行は NULL になります。NULL の行では、
実際の文字列は空文字列として格納されます (LEB128 の長さは 0) 。なお、NULL ではない空
文字列も LEB128 の長さは 0 なので、この 2 つのケースを区別できるのはマスクバイトだけです。たとえば、次のクエリです。
LowCardinality
LowCardinality が透過的に扱われる RowBinary とは異なり、Nativeフォーマット では辞書ベースの列指向エンコーディングを使用します。カラムは、バージョンプレフィックス、一意な値の辞書、その辞書を参照する整数の索引の Array としてエンコードされます。
カラムは
LowCardinality(Nullable(T)) として定義できますが、Nullable(LowCardinality(T)) として定義することはできません。常にサーバーエラーになります。1 の UInt64(LE) で、カラムごとに 1 回書き込まれます。続いて、ブロック ごとに次の内容が書き込まれます。
UInt64(LE)—IndexesSerializationTypeのビットフィールド。ビット 0–7 は索引の幅を表します (0 = UInt8、1 = UInt16、2 = UInt32、3 = UInt64) 。ビット 8 (NeedGlobalDictionaryBit) は Nativeフォーマット では決して設定されません (これが現れた場合、サーバーは例外をスローします) 。ビット 9 は追加の辞書キーが存在することを示します。ビット 10 は辞書をリセットする必要があることを示します。UInt64(LE)— 辞書キー数。続いて、キーが内部型のエンコーディングを使って一括シリアライゼーションされます。UInt64(LE)— 行数。続いて、索引値が適切な UInt 幅を使って一括シリアライゼーションされます。
String では空文字列、数値型では 0) 。LowCardinality(Nullable(T)) の場合、索引 0 は NULL を表し、キーは Nullable ラッパーなしでシリアライゼーションされます。
たとえば、5 行 ['foo', 'bar', 'baz', 'foo', 'bar'] を持つ LowCardinality(String) は次のように表されます。
LowCardinality(Nullable(String)) では、索引 0 は NULL になります:
Array
- 累積
UInt64オフセットが N 個 (リトルエンディアン、各 8 バイト) 。行iの要素数はoffset[i] - offset[i-1]で、offset[-1]は暗黙的に 0 とみなされます。 - 全行にわたるすべてのネスト要素を、連続した領域にまとめて一括シリアライズします。
[[0, 10], [1, 11], [2, 12]] を持つ Array(UInt32) の場合:
Array(String) [[], ['0'], ['0','1'], ['0','1','2']] の場合:
Map
Map(K, V) は Array(Tuple(K, V)) としてエンコードされます。つまり、配列オフセットの後にすべてのキーが並び、その後にすべての値が並びます。これは、各エントリごとにキーと値が交互に格納される RowBinary とは異なります。
たとえば、3 行の Map(String, UInt64) [{'a':0,'b':10}, {'a':1,'b':11}, {'a':2,'b':12}] は次のようにエンコードされます。
Variant
Variant カラムは次のようにエンコードされます。
UInt64(LE)の discriminator モード prefix (0= BASIC、1= COMPACT) 。Nativeフォーマット の出力では通常 BASIC (0) が使用されます。COMPACT モードは、use_compact_variant_discriminators_serializationを有効にして保存されたデータを読み取る際に現れることがあります。- N 個の
UInt8discriminant。各行に 1 つずつ対応します。 - 各 Variant 型のデータは、それに一致する行だけを含む個別のバルクカラムとして、discriminant の順に格納されます。
[0::UInt32, 'hello', NULL, 3::UInt32, 'hello'] を持つ Variant(String, UInt32) の場合 (ソート順: String = 0、UInt32 = 1) :
Dynamic
Dynamic は構造プレフィックスに続く Variant カラムとしてシリアライズされます。
構造プレフィックスには、UInt64(LE) のシリアル化バージョン、動的型の数 (VarUInt として) 、続いて文字列としての型名が含まれます。バージョン V1 では、互換性のため型の数が 2 回書き込まれます。後続のデータは Variant カラムで、その型リストは動的型に内部 SharedVariant 型を加えたものをアルファベット順に並べたものです。
たとえば、5 行の [0::UInt32, 'hello', NULL, 3::UInt32, 'hello'] を持つ Dynamic の場合:
JSON
JSON は列指向の構造でシリアライズされます。このエンコーディングは複雑で、バージョンにも依存します。具体的には、シリアル化バージョン、動的パス名、共有データレイアウトを含む構造プレフィックスに続いて、型付きパス (それぞれをバルクカラムとして格納) 、動的パス (それぞれを Dynamic カラムとして格納) 、さらにオーバーフローパス用の共有データで構成されます。
より簡単に相互運用できるようにするには、JSON カラムを通常の JSON テキスト文字列 (各行につき 1 つの String) としてシリアライズする設定 output_format_native_write_json_as_string=1 の使用を検討してください。