Типы данных
В данном разделе описано, какие типы данных поддерживает YTsaurus, как они описываются в схеме и как они представляются в форматах.
Общая информация
YTsaurus поддерживает набор примитивных типов:
string;integer;boolean;float;double;date;datetime;timestamp;interval.
А так же следующие композитные (сложные) типы:
optional;list;struct;tuple;variant;tagged.
Задать тип в схеме таблицы можно одним из двух способов:
- с помощью ключей
typeи (необязательно)required— исторически первый способ, но так можно задать лишь примитивные или опциональные примитивные типы; - с помощью ключа
type_v3.
В ключе type всегда ожидается строка.
В ключе type_v3 ожидается либо строка для примитивных типов, либо YSON-словарь.
YSON-словарь всегда имеет ключ type_name, в котором хранится имя типа.
Остальные ключи зависят от конкретного типа и описаны ниже.
Описание типов в схеме
Примитивные типы
Примитивные типы можно задать в схеме как с помощью ключа type, так и с помощью ключа type_v3.
Если примитивный тип T задаётся с помощью type, YTsaurus дополнительно проверит ключ required в схеме:
required=%true— колонка будет иметь строго заданный тип. ЗначениеNullили отсутствие значения не допускаются;required=%false— колонка будет иметь типoptional<T>— будут допустимы все значения примитивного типа и значениеNull.
В таблице перечислены поддерживаемые типы и их представление в ключах type/type_v3.
| Описание | Представление в type |
Представление в type_v3 |
|---|---|---|
целое число в диапазоне [-2^63, 2^63-1] |
int64 |
int64 |
целое число в диапазоне [-2^31, 2^31-1] |
int32 |
int32 |
целое число в диапазоне [-2^15, 2^15-1] |
int16 |
int16 |
целое число в диапазоне [-2^7, 2^7-1] |
int8 |
int8 |
целое число в диапазоне [0, 2^64-1] |
uint64 |
uint64 |
целое число в диапазоне [0, 2^32-1] |
uint32 |
uint32 |
целое число в диапазоне [0, 2^16-1] |
uint16 |
uint16 |
целое число в диапазоне [0, 2^8-1] |
uint8 |
uint8 |
| 8-байтное число с плавающей точкой соответствующее стандарту IEEE 754 | double |
double |
| 4-байтное число с плавающей точкой соответствующее стандарту IEEE 754 | float |
float |
стандартный булев тип true/false |
boolean |
bool (отличие от type) |
| произвольная последовательность байт | string |
string |
| корректная UTF8 последовательность | utf8 |
utf8 |
| строка, содержащая валидный JSON | json |
json |
| UUID, произвольная последовательность 16 байт (хранится бинарное представление) | uuid |
uuid |
целое число в диапазоне [-53375809, 53375808 - 1], выражает число дней, прошедших с unix-эпохи; выражаемый диапазон времени около 145'000 лет в прошлое и в будущее см. раздел про временные типы |
date32 |
date32 |
целое число в диапазоне [-53375809 * 86400, 53375808 * 86400 - 1], выражает число секунд, прошедших с unix-эпохи; выражаемый диапазон времени около 145'000 лет в прошлое и в будущее см. раздел про временные типы |
datetime64 |
datetime64 |
целое число в диапазоне [-53375809 * 86400 * 10^6, 53375808 * 86400 * 10^6 - 1], выражает число микросекунд, прошедших с unix-эпохи; выражаемый диапазон времени около 145'000 лет в прошлое и в будущее см. раздел про временные типы |
timestamp64 |
timestamp64 |
целое число в диапазоне [-9223339708800000000, 9223339708800000000], выражает число микросекунд между двумя таймстемпами типа timestamp64 см. раздел про временные типы |
interval64 |
interval64 |
целое число в диапазоне [0, 49673 - 1], выражает число дней, прошедших с unix-эпохи; выражаемый диапазон дат: [1970-01-01, 2105-12-31] см. раздел про временные типы |
date |
date |
целое число в диапазоне [0, 49673 * 86400 - 1], выражает число секунд, прошедших с unix-эпохи; выражаемый диапазон времён: [1970-01-01T00:00:00Z, 2105-12-31T23:59:59Z] см. раздел про временные типы |
datetime |
datetime |
целое число в диапазоне [0, 49673 * 86400 * 10^6 - 1], выражает число микросекунд, прошедших с unix-эпохи; выражаемый диапазон времён: [1970-01-01T00:00:00Z, 2105-12-31T23:59:59.999999Z] см. раздел про временные типы |
timestamp |
timestamp |
целое число в диапазоне [- 49673 * 86400 * 10^6 + 1, 49673 * 86400 * 10^6 - 1], выражает число микросекунд между двумя таймстемпами типа timestamp см. раздел про временные типы |
interval |
interval |
(начиная с версии 25.3) тип date с информацией о часовом поясе см раздел часовые пояса |
tz_date | tz_date |
(начиная с версии 25.3) тип datetime с информацией о часовом поясе см раздел часовые пояса |
tz_datetime | tz_datetime |
(начиная с версии 25.3) тип timestamp с информацией о часовом поясе см раздел часовые пояса |
tz_timestamp | tz_timestamp |
(начиная с версии 25.3) тип date32 с информацией о часовом поясе см раздел часовые пояса |
tz_date32 | tz_date32 |
(начиная с версии 25.3) тип datetime64 с информацией о часовом поясе см раздел часовые пояса |
tz_datetime64 | tz_datetime |
(начиная с версии 25.3) тип timestamp64 с информацией о часовом поясе см раздел часовые пояса |
tz_timestamp64 | tz_timestamp64 |
| произвольная YSON-структура, физически представляется последовательностью байт, не может иметь атрибут required=%true |
any |
yson (отличие от type) |
системный сингулярный тип, возможно единственное значение null (заведение отдельной колонки с таким типом не имеет смысла, мы не ожидаем встретить этот тип в пользовательских таблицах, но тип полезен для интеграции с YQL) |
null |
null |
сингулярный тип, возможно единственное значение null, это тип, отличный от null (заведение отдельной колонки с таким типом не имеет особого смысла, мы не ожидаем встретить этот тип в пользовательских таблицах, но тип полезен для интеграции с YQL) |
void |
void |
Примеры в схеме:
type_v3=utf8
type_v3=bool
type_v3=yson
Временные типы
Есть два набора типов для работы со временем. Исторически, первые появившиеся в системе это date, datetime, timestamp, interval. Эти типы позволяют выражать времена от начала 1970 года до конца 2105 года. Позже появились типы date32, datetime64, timestamp64 и interval64. Эти типы позволяют выражать времена в более широком диапазоне, около 145'000 лет в прошлое и столько же в будущее. Предпочтительнее использовать последние типы, у них более широкий диапазон значений.
Все времена подразумевают использование григорианского календаря. При работе с моментами времени в далёком прошлом, стоит иметь ввиду, что YT никак не учитывает переход на григорианский каледнарь, который происходил в разных государствах в разное время. YT считает, что григорианский календарь использовался всегда.
Часовые пояса
Tипы tz_timestamp64, tz_datetime64, tz_date32, tz_timestamp, tz_datetime, tz_date хранят информацию о времени с учётом часового пояса. Логически эти типы хранят пару:
- таймстемп, целое число из соответствующего типа "без часовых поясов", число выражает момент времени в часовом поясе UTC
- название часового пояса из базы данных часовых поясов IANA
Ниже описано внутреннее представление значений этих типов. Некоторые высокоуровневые инструменты предоставляют удобный способ работать с этими типами.
|
tz-тип |
соответствующий тип без часового пояса |
нижележащий целочисленный тип |
диапазон значений целочисленного типа |
физическая величина |
|
tz_date |
date |
Uint16 |
|
дни |
|
tz_datetime |
datetime |
Uint32 |
|
секунды |
|
tz_timestamp |
timestmap |
Uint64 |
|
микросекунды |
|
tz_date32 |
date32 |
Int32 |
|
дни |
|
tz_datetime64 |
datetime64 |
Int64 |
|
секунды |
|
tz_timestamp64 |
timestamp64 |
Int64 |
|
микросекунды |
Сериализация этой пары в строку устроена следующим образом.
- целое число записывается в предсортированном представлении (см ниже);
- название часового пояса записывается полностью, например
Europe/Moscow.
Предсортированное представление целого числа получается следующим образом.
- Записываем число в big-endian представлении.
- Если нижележащий целочисленный тип знаковый (типы
tz_date32,tz_datetime64,tz_timestamp64), то инвертируем старший (знаковый) бит, для типов, где нижележащий тип беззнаковый этот шаг пропускается.
Пример: мы хотим сохранить момент времени 2025-01-01T00:00:00 в часовом поясе Москвы в типе tz_datetime64. Для этого мы делаем следующее.
1. Переводим этот момент времени в UTC, получается 2024-12-31T21:00:00Z
2. Переводим UTC время в unix timestamp, получается 1735678800
3. Записываем этот timestamp в big-endian представлении, получается "\x00\x00\x00\x00\x67\x74\x5b\x50"
4. Т.к. тип tz_datetime64 основан на знаковом типе Int64, мы флипаем старший бит, получается "\x80\x00\x00\x00\x67\x74\x5b\x50".
5. Дописываем информацию о временной зоне, получается "\x80\x00\x00\x00\x67\x74\x5b\x50Europe/Moscow".
Десятичное число / decimal
Значения типа decimal(p, s) — вещественные числа с указанной точностью.
Чтобы задать этот тип в схеме, укажите следующие ключи:
type_name- значениеdecimal;precision- общее число десятичных цифр в представлении числа,precisionдолжен находиться в диапазоне[1, 35];scale- число десятичных цифр в представлении числа, которые идут после десятичной точки,scaleдолжно находится в диапазоне[0, precision].
Пример в схеме:
type_v3={
type_name=decimal;
precision=10;
scale=2;
}
Значения 3.14, -2.71, 9.99 могут иметь тип decimal(3, 2) (precision=3, scale=2).
Тип поддерживает несколько специальных значений: nan, +inf, -inf.
Описание бинарного представления decimal
Для decimal-чисел есть специальное бинарное представление,
которое по умолчанию используется во многих форматах, например, yson.
В этом представлении значения типов decimal(p, s) представляются бинарными строками. Длина бинарной строки
зависит от precision.
| Precision | Число бит в представлении | Число байт в представлении |
|---|---|---|
| 1-9 | 32 | 4 |
| 10-18 | 64 | 8 |
| 19-38 | 128 | 16 |
| 39-76 | 256 | 32 |
Чтобы получить бинарное представление decimal-числа, нужно сделать следующие шаги. Шаги будут проиллюстрированы значениями 3.1415, -2.7182 типа decimal(5, 4).
- Возьмите целое число, образованное десятичными цифрами значения. Число бит выбирается из
precisionпо таблице выше. В данном примере — 32-битные числа31415,-27182. - Запишите число в big-endian представлении. В данном примере — строки
\x00\x00\x7A\xB7,\xFF\xFF\x95\xD2. - Инвертируйте старший бит. В данном примере — строки
\x80\x00\7A\xB7,\x7F\xFF\x95\xD2.
Целочисленные представления специальных значений nan, +inf, -inf для первого шага представлены в таблице ниже:
| Специальное значение | Целочисленное представление |
|---|---|
nan |
INT_MAX |
+inf |
INT_MAX - 1 |
-inf |
- INT_MAX + 1 |
Обратите внимание
На текущий момент при работе с YQL поддерживаются только decimal со значением precision не более 35.
Опциональный тип / optional
Тип optional<T> означает, что значение может иметь тип T или отсутствовать.
Обратите внимание
Каждое применение optional для типа добавляет новые значения.
Например, тип optional<optional<bool>> может иметь следующие значения:
- внешний
optionalне заполнен; - внешний
optionalзаполнен, внутренний не заполнен; - все
optionalзаполнены, значениеtrueилиfalse.
Старые колонки, в которых заданы атрибуты type=T;required=false, соответствуют типу optional<T>, заданному через type_v3.
Чтобы задать тип optional, укажите ключи:
type_name— значениеoptional;item— описание типа элемента.
Примеры в схеме:
type_v3={
type_name=optional;
item=string;
}
type_v3={
type_name=optional;
item={
type_name=optional;
item=bool;
}
}
Список / list
Значения типа list<T> — списки элементов типа T.
Чтобы задать тип в схеме, укажите ключи:
type_name— значениеlist;item— описание типа элемента.
Примеры в схеме:
type_v3={
type_name=list;
item=string;
}
type_v3={
type_name=list;
item={
type_name=list;
item=double;
}
}
Структура / struct
Набор именованных полей с указанными типами значений.
Чтобы задать этот тип в схеме, укажите ключи:
type_name— значениеstruct;members— список словарей с ключами:name— имя поля, должно быть непустой utf8-строкой;type— тип поля.
Примеры в схеме:
type_v3={
type_name=struct;
members=[
{
name=foo;
type=int32;
};
{
name=bar;
type={
type_name=optional;
item=string;
}
};
]
}
Кортеж / tuple
Набор безымянных полей с фиксированными типами.
Чтобы задать этот тип, в схеме нужно указать следующие ключи:
type_name— значениеtuple;elements— список словарей с ключами:type— тип элемента.
Пример в схеме:
type_v3={
type_name=tuple;
elements=[
{
type=double;
};
{
type=double;
};
]
}
Вариант / variant
Вариант — строго одно значение из фиксированного набора типов.
Вариант бывает двух типов:
- Вариант над структурой. Каждый тип имеет имя (как в структуре) и каждое значение варианта маркировано именем соответствующего элемента варианта;
- Вариант над кортежем. тогда все элементы безымянные и каждое значение маркируется индексом.
Чтобы задать этот тип, в схеме укажите ключи:
type_name— значениеvariant;elementsилиmembers(но не оба), ключи имеют структуру аналогичную этим ключам вtuple/struct:
elements— для варианта с безымянными элементами, сам ключ содержит список словарей с ключами:type— тип элемента;
members— для варианта с именованными элементами, сам ключ содержит список словарей с ключами:name— имя элемента, должно быть непустой utf8-строкой;type— описание типа элемента.
Пример в схеме:
type_v3={
type_name=variant;
members=[
{
name=int_field;
type=int64;
};
{
name=string_field;
type=string;
};
]
}
type_v3={
type_name=variant;
elements=[
{
type=int32;
};
{
type=string;
};
{
type=double;
};
]
}
Словарь / dict
Словарь — это последовательность пар ключ-значение.
YTsaurus не проверяет уникальность ключей или их порядок.
Однако большая часть клиентов при обработке будет загружать данные в реальный словарь, и значения для повторяющихся ключей будут утеряны.
Чтобы задать этот тип, в схеме укажите ключи:
type_name— значениеdict;key— описание типа ключа;value— описание типа значения.
Пример в схеме:
type_v3={
type_name=dict;
key=int64;
value={
type_name=optional;
item=string;
};
}
Тегированное значение / tagged
Тип tagged позволяет аннотировать другие типы строкой. Значением типа tagged<TAG_NAME,T> может быть любое значение типа T,
однако сами типы будут считаться различными в тех местах, где YTsaurus сравнивает схемы. Например, когда проверяется возможность объединить две таблицы в одну.
Чтобы задать этот тип, в схеме укажите ключи:
type_name— значениеtagged;tag— имя тега, должно быть непустой utf8-строкой;item— описание типа элемента.
—
Пример в схеме:
type_v3={
type_name=tagged;
tag="image/svg";
item="string";
}
Представление сложных типов в форматах
Для чтения и записи таблиц используются форматы.
Не все форматы поддерживают сложные данные, некоторые из них, например, dsv / schemaful_dsv, будут возвращать ошибку при попытке прочитать сложное значение. Например, Values of type "any" are not supported by the chosen format.
YSON
Существует два YSON представления сложных типов. Различаются представления типов struct и variant:
представление по умолчанию более удобно в использовании,
альтернативное представление несколько эффективнее в хранении и обработке.
Представления переключаются флагом complex_type_mode. Возможные значения: named / positional.
Ниже описаны представления типов. Если не указано иное, представление типа не зависит от настройки complex_type_mode.
Есть два представления для типа dict со строковыми ключами: по умолчанию используется positional представление в виде списка (так как данные хранятся в YTsaurus). Для удобства восприятия можно включить режим named с помощью флага string_keyed_dict_mode.
Примитивные типы
Примитивные типы представляются прямолинейно одним YSON-значением.
В таблице приведено соответствие примитивных типов и YSON-типов.
type / type_v3 |
Представление в yson |
|---|---|
int64 |
знаковое число |
int32 |
знаковое число |
int16 |
знаковое число |
int8 |
знаковое число |
uint64 |
беззнаковое число |
uint32 |
беззнаковое число |
uint16 |
беззнаковое число |
uint8 |
беззнаковое число |
double |
число с плавающей точкой |
boolean / bool |
булево значение |
string |
строка |
utf8 |
строка |
date |
беззнаковое число, см ниже |
datetime |
беззнаковое число, см ниже |
timestamp |
беззнаковое число, см ниже |
interval |
знаковое число |
uuid |
строка с бинарными данными, см ниже |
any / yson |
зависит от значения |
null |
# |
void |
# |
Временные типы
В yson-формате есть опция time_mode, которая управляет представлением типов date, datetime, timestamp. Ее возможные значения такие:
binary(по-умолчанию) — используется представление в виде беззнакового числа, обозначающего число дней / секунд / миллисекунд с начала unix эпохи.text— используется строковое представление, примеры представленияdate,datetime,timestampсоответственно такие:
2022-01-02,2022-01-02T03:04:05Z,2022-01-02T03:04:05.123456Z.
UUID
В yson-формате есть опция uuid_mode, которая управляет представлением типа uuid. Её возможные значения:
binary(по умолчанию) — используется бинарное представление из 16 байт.text_yt— используется строковое представление, в формате YTsaurus из 4 групп, например61626364-65666768-696a6b6c-6d6e6f70;text_yql— используется строковое представление, в формате YQL из 5 групп более похожим на представление RFC, например64636261-6665-6867-696a-6b6c6d6e6f70.
Decimal
В YSON формате есть опция decimal_mode, которая управляет представлением типа decimal. Ее возможные значения:
binary(по-умолчанию) — кодируется бинарной строкой с бинарным представлениемdecimal-числа.text— используется текстовое представлениеdecimal-числа.
Optional
Представление типа optional зависит от его внутреннего типа.
Это необходимо для обратной совместимости с колонками, для которых проставлено required=%false.
Если T — произвольный тип, который не является optional, то optional<T> представляется следующим образом:
Nullзначениеoptionalпредставляется#;- в противном случае используется обычное представление значения типа
T.
Если T — тип, который является optional, то optional<T> представляется следующим образом:
Nullзначение внешнегоoptionalпредставляется#;- в противном случае используется представление
[ v ](yson-список длины 1), гдеv— YSON-представление значения типаT.
Примеры значений, тип optional<int64>:
#
-42
Примеры значений, тип optional<optional<int64>>:
#
[ # ]
[ -42 ]
List
Тип list<T> кодируется YSON-списком, элементы которого представляют собой кодированное представление элементов типа T.
Примеры значений, тип list<int64>:
[]
[42; -1;]
Struct
Представление структуры зависит от значения флага complex_type_mode.
Именованное представление (по умолчанию)
Описываемое представление для случая,
когда опция YSON формата complex_type_mode не выставлена или выставлено значение complex_type_mode=named.
Структура представлена YSON-словарём, где ключи — имена полей, а значения — их содержимое.
Примеры значений, тип struct<Foo:int64;Bar:optional<utf8>>:
{Foo=42;Bar=#;}
{Foo=-5;Bar="minus five";}
Позиционное представление
В случае, если для YSON-формата выставлена опция complex_type_mode=positional, используется другое представление.
Структура кодируется YSON-списком, где на i-й позиции стоит YSON-представление i-го поля структуры.
Длина списка может быть меньше, чем число полей в структуре, тогда оставшиеся типы должны иметь тип optional<T>,
и считается, что поля имеют пустое optional значение.
Примеры значений, тип struct<Foo:int64;Bar:optional<utf8>>:
[42; #;]
[42]
[-5;"minus five";]
Tuple
Тип tuple кодируется YSON-списком фиксированной длины. На i-м месте стоит кодированное значение i-го поля.
Примеры значений, тип tuple<int64;optional<utf8>>:
[42; #;]
[-5;"minus five";]
Variant
Неименованный variant
Неименованный вариант представлен YSON-списком длины 2 из следующих элементов:
- номер альтернативы (индексация с 0);
- кодированное значение соответствующей альтернативы.
Примеры значений, тип variant<int64;optional<utf8>>:
[0; 42]
[1; #]
[1; "foo bar";]
Именованный вариант variant
Именованное представление (по умолчанию)
Описываемое представление для случая, когда опция YSON-формата complex_type_mode не выставлена или выставлена в значение complex_type_mode=named.
Именованный вариант представляется YSON-списком длины 2 из следующих элементов:
- имя альтернативы;
- кодированное значение соответствующей альтернативы.
Примеры значений, тип `variant<Foo:int64;Bar:optional
[Foo; 42]
[Bar; #]
[Bar; "foo bar";]
Позиционное представление
Если для формата выставлена опция complex_type_mode=positional.
Именованный вариант представлен YSON-списком длины 2 из следующих элементов:
- индекс альтернативы;
- кодированное значение соответствующей альтернативы.
Примеры значений, тип variant<Foo:int64;Bar:optional<utf8>>:
[Foo; 42]
[Bar; #]
[Bar; "foo bar";]
Dict
Тип dict по умолчанию представлен YSON-списком, где каждый элемент — YSON-список из двух элементов: ключ и значение.
Примеры значений типа dict<int32;string>:
[[1;"one"];[4;"four"]]
[]
dict может быть представлен YSON-словарём, однако YSON-словарь поддерживает только строки в качестве ключей, а dict поддерживает и другие ключи.
Dict with string keys
Представление словаря со строковыми ключами зависит от значения флага string_keyed_dict_mode.
Позиционное представление (по умолчанию)
Описываемое представление для случая, когда опция YSON формата string_keyed_dict_mode не выставлена или выставлена в значение string_keyed_dict_mode=positional.
См. выше
Примеры значений типа dict<string;int32>:
[["one";1];["four";4]]
Именованное представление
Если для YSON-формата выставлена опция string_keyed_dict_mode=named, используется другое представление.
dict кодируется YSON-словарём.
Примеры значений типа dict<string;int32>:
{one=1; four=4}
Tagged
Тип tagged не меняет YSON представление его элемента.