Типы данных

В данном разделе описано, какие типы данных поддерживает 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-байтное число double double
вещественное 4-байтное число 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
произвольная 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 считает, что григорианский календарь использовался всегда.

Десятичное число / 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).

  1. Возьмите целое число, образованное десятичными цифрами значения. Число бит выбирается из precision по таблице выше. В данном примере — 32-битные числа 31415, -27182.
  2. Запишите число в big-endian представлении. В данном примере — строки \x00\x00\x7A\xB7, \xFF\xFF\x95\xD2.
  3. Инвертируйте старший бит. В данном примере — строки \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 представление его элемента.