데이터 타입 이진 인코딩
데이터 타입 이진 인코딩 (Binary Encoding)
ClickHouse 데이터 타입을 이진 인코딩·디코딩할 때 사용할 수 있는 이진 형식을 정의한 명세 문서예요. 각 데이터 타입은 타입을 나타내는 1바이트와 옵션으로 붙는 추가 정보로 인코딩돼요.
출처: 문서
본문
이 명세는 ClickHouse 데이터 타입의 이진 인코딩과 디코딩에 사용할 수 있는 이진 형식을 설명해요. 이 형식은 Dynamic 컬럼의 이진 직렬화에 사용되며, 해당 설정 아래에서 입력/출력 형식 RowBinaryWithNamesAndTypes와 Native에서도 사용할 수 있어요.
아래 표는 각 데이터 타입이 이진 형식에서 어떻게 표현되는지를 보여줘요. 각 데이터 타입 인코딩은 타입을 나타내는 1바이트와 몇 가지 옵션 추가 정보로 구성돼요. 이진 인코딩의 var_uint는 크기가 VLQ(Variable-Length Quantity, 가변 길이 양) 압축으로 인코딩된다는 뜻이에요.
| ClickHouse 데이터 타입 | 이진 인코딩 |
|---|---|
Nothing |
0x00 |
UInt8 |
0x01 |
UInt16 |
0x02 |
UInt32 |
0x03 |
UInt64 |
0x04 |
UInt128 |
0x05 |
UInt256 |
0x06 |
Int8 |
0x07 |
Int16 |
0x08 |
Int32 |
0x09 |
Int64 |
0x0A |
Int128 |
0x0B |
Int256 |
0x0C |
Float32 |
0x0D |
Float64 |
0x0E |
Date |
0x0F |
Date32 |
0x10 |
DateTime |
0x11 |
DateTime(time_zone) |
0x12<var_uint_time_zone_name_size><time_zone_name_data> |
DateTime64(P) |
0x13<uint8_precision> |
DateTime64(P, time_zone) |
0x14<uint8_precision><var_uint_time_zone_name_size><time_zone_name_data> |
String |
0x15 |
FixedString(N) |
0x16<var_uint_size> |
Enum8 |
0x17<var_uint_number_of_elements><var_uint_name_size_1><name_data_1><int8_value_1>...<var_uint_name_size_N><name_data_N><int8_value_N> |
Enum16 |
0x18<var_uint_number_of_elements><var_uint_name_size_1><name_data_1><int16_little_endian_value_1>...><var_uint_name_size_N><name_data_N><int16_little_endian_value_N> |
Decimal32(P, S) |
0x19<uint8_precision><uint8_scale> |
Decimal64(P, S) |
0x1A<uint8_precision><uint8_scale> |
Decimal128(P, S) |
0x1B<uint8_precision><uint8_scale> |
Decimal256(P, S) |
0x1C<uint8_precision><uint8_scale> |
UUID |
0x1D |
Array(T) |
0x1E<nested_type_encoding> |
Tuple(T1, ..., TN) |
0x1F<var_uint_number_of_elements><nested_type_encoding_1>...<nested_type_encoding_N> |
Tuple(name1 T1, ..., nameN TN) |
0x20<var_uint_number_of_elements><var_uint_name_size_1><name_data_1><nested_type_encoding_1>...<var_uint_name_size_N><name_data_N><nested_type_encoding_N> |
Set |
0x21 |
Interval |
0x22<interval_kind> (interval kind 이진 인코딩 참고) |
Nullable(T) |
0x23<nested_type_encoding> |
Function |
0x24<var_uint_number_of_arguments><argument_type_encoding_1>...<argument_type_encoding_N><return_type_encoding> |
AggregateFunction(function_name(param_1, ..., param_N), arg_T1, ..., arg_TN) |
0x25<var_uint_version><var_uint_function_name_size><function_name_data><var_uint_number_of_parameters><param_1>...<param_N><var_uint_number_of_arguments><argument_type_encoding_1>...<argument_type_encoding_N> (aggregate function parameter 이진 인코딩 참고) |
LowCardinality(T) |
0x26<nested_type_encoding> |
Map(K, V) |
0x27<key_type_encoding><value_type_encoding> |
IPv4 |
0x28 |
IPv6 |
0x29 |
Variant(T1, ..., TN) |
0x2A<var_uint_number_of_variants><variant_type_encoding_1>...<variant_type_encoding_N> |
Dynamic(max_types=N) |
0x2B<uint8_max_types> |
Custom type (Ring, Polygon 등) |
0x2C<var_uint_type_name_size><type_name_data> |
Bool |
0x2D |
SimpleAggregateFunction(function_name(param_1, ..., param_N), arg_T1, ..., arg_TN) |
0x2E<var_uint_function_name_size><function_name_data><var_uint_number_of_parameters><param_1>...<param_N><var_uint_number_of_arguments><argument_type_encoding_1>...<argument_type_encoding_N> (aggregate function parameter 이진 인코딩 참고) |
Nested(name1 T1, ..., nameN TN) |
0x2F<var_uint_number_of_elements><var_uint_name_size_1><name_data_1><nested_type_encoding_1>...<var_uint_name_size_N><name_data_N><nested_type_encoding_N> |
JSON(max_dynamic_paths=N, max_dynamic_types=M, path Type, SKIP skip_path, SKIP REGEXP skip_path_regexp) |
0x30<uint8_serialization_version><var_int_max_dynamic_paths><uint8_max_dynamic_types><var_uint_number_of_typed_paths><var_uint_path_name_size_1><path_name_data_1><encoded_type_1>...<var_uint_number_of_skip_paths><var_uint_skip_path_size_1><skip_path_data_1>...<var_uint_number_of_skip_path_regexps><var_uint_skip_path_regexp_size_1><skip_path_data_regexp_1>... |
BFloat16 |
0x31 |
Time |
0x32 |
Time64(P) |
0x34<uint8_precision> |
QBit(T, N) |
0x36<element_type_encoding><var_uint_dimension> |
QBit(T, N, stride) |
0x37<element_type_encoding><var_uint_dimension><var_uint_stride> |
JSON 타입의 uint8_serialization_version 바이트는 직렬화 버전을 나타내요. 현재 버전은 항상 0이지만, 앞으로 JSON 타입에 새로운 인자가 추가되면 바뀔 수 있어요.
QBit 타입에서는 stride가 차원 N과 다를 때만 0x37 인코딩을 사용해요. stride == N일 때(QBit(Float32, 4, 4)처럼 세 번째 인자를 명시적으로 작성한 경우 포함) 타입은 두 인자 형태인 QBit(T, N)으로 정규화되어 위의 0x36으로 인코딩되므로, 이진 인코딩은 stride가 없는 QBit와 바이트 단위로 동일하게 유지돼요.
Interval kind 이진 인코딩
아래 표는 Interval 데이터 타입의 서로 다른 interval kind가 어떻게 인코딩되는지 보여줘요.
| Interval kind | 이진 인코딩 |
|---|---|
Nanosecond |
0x00 |
Microsecond |
0x01 |
Millisecond |
0x02 |
Second |
0x03 |
Minute |
0x04 |
Hour |
0x05 |
Day |
0x06 |
Week |
0x07 |
Month |
0x08 |
Quarter |
0x09 |
Year |
0x1A |
Aggregate function parameter 이진 인코딩
아래 표는 AggregateFunction과 SimpleAggregateFunction의 매개변수가 어떻게 인코딩되는지 보여줘요. 매개변수 인코딩은 매개변수의 타입을 나타내는 1바이트와 값 자체로 구성돼요.
| 매개변수 타입 | 이진 인코딩 |
|---|---|
Null |
0x00 |
UInt64 |
0x01<var_uint_value> |
Int64 |
0x02<var_int_value> |
UInt128 |
0x03<uint128_little_endian_value> |
Int128 |
0x04<int128_little_endian_value> |
UInt256 |
0x05<uint256_little_endian_value> |
Int256 |
0x06<int256_little_endian_value> |
Float64 |
0x07<float64_little_endian_value> |
Decimal32 |
0x08<var_uint_scale><int32_little_endian_value> |
Decimal64 |
0x09<var_uint_scale><int64_little_endian_value> |
Decimal128 |
0x0A<var_uint_scale><int128_little_endian_value> |
Decimal256 |
0x0B<var_uint_scale><int256_little_endian_value> |
String |
0x0C<var_uint_size><data> |
Array |
0x0D<var_uint_size><value_encoding_1>...<value_encoding_N> |
Tuple |
0x0E<var_uint_size><value_encoding_1>...<value_encoding_N> |
Map |
0x0F<var_uint_size><key_encoding_1><value_encoding_1>...<key_encoding_N><value_encoding_N> |
IPv4 |
0x10<uint32_little_endian_value> |
IPv6 |
0x11<uint128_little_endian_value> |
UUID |
0x12<uuid_value> |
Bool |
0x13<bool_value> |
Object |
0x14<var_uint_size><var_uint_key_size_1><key_data_1><value_encoding_1>...<var_uint_key_size_N><key_data_N><value_encoding_N> |
AggregateFunctionState |
0x15<var_uint_name_size><name_data><var_uint_data_size><data> |
Negative infinity |
0xFE |
Positive infinity |
0xFF |