Сопоставление типов данных: SPYT, Spark и YTsaurus
В этой статье описано сопоставление типов данных в YTsaurus и типов данных в Spark при чтении и записи.
Особенности
-
Указания типов: некоторые сопоставления могут быть изменены указаниями типов в метаданных полей, позволяя более точный контроль над преобразованием типов.
-
Точность Decimal: YTsaurus ограничивает
precisionтипаdecimalзначением 35 (неscale). Подробнее про Decimal -
Строковые типы: опция конфигурации
stringToUtf8контролирует, сопоставляются ли строки с типамиstringилиutf8в YTsaurus. Пример:import spyt from pyspark.sql import Row from pyspark.sql.types import StructType, StructField, StringType, BinaryType spark.createDataFrame( spark.sparkContext.parallelize([Row("string", b"binary")]), StructType([ StructField("string", StringType(), nullable=False), StructField("binary", BinaryType(), nullable=False), ]) ).write \ .option("string_to_utf8", "true") \ .yt("//path/to/table") -
Составные типы: сложные типы наподобие структур, массивов и словарей рекурсивно сопоставляются с использованием тех же правил для их элементарных типов.
-
Тип
floatпри чтении сопоставляется по-разному в зависимости от положения в схеме:- колонка верхнего уровня →
FloatType; - элемент внутри составного типа (
Array,Dict,Struct,Tuple,Variant) →DoubleType.
Это связано с особенностью формата YSON: в YSON нет 4-байтного float-узла, поэтому
floatвнутри составных типов хранится как 8-байтный double. Чтобы избежать потери данных при чтении, SPYT преобразует его вDoubleType. Колонки верхнего уровня читаются по wire-протоколу, где типfloatсохраняется какFloatType. - колонка верхнего уровня →
-
«Arrow не поддерживается»: для типов с такой пометкой при включённой опции
spark.yt.read.arrow.enabled(по умолчаниюtrue) SPYT автоматически переключается на wire-протокол.Важно
Если хотя бы одна колонка схемы содержит тип без поддержки Arrow, вся таблица читается через wire-протокол, включая остальные колонки. При проектировании схемы это стоит учитывать, если важна производительность чтения.
Подробнее про некоторые специальные методы для работы с типами данных можно почитать в статьях Опции чтения и Опции записи.
Сопоставление типов при чтении из YTsaurus
| Тип YTsaurus | Тип Spark (Базовый) | Тип Spark (Расширенный) | Примечания |
|---|---|---|---|
| null | NullType | NullType | |
| int64 | LongType | LongType | |
| uint64 | DecimalType(20, 0) | UInt64Type | |
| float | FloatType/DoubleType | FloatType/DoubleType | Верхний уровень: FloatType; внутри составного типа: DoubleType (см. Особенности п. 5). Arrow не поддерживается |
| double | DoubleType | DoubleType | |
| boolean | BooleanType | BooleanType | |
| string | StringType | StringType | |
| binary | BinaryType | BinaryType | |
| any/yson | BinaryType | YsonType | YsonType — кастомный тип SPYT (см. раздел ниже) |
| int8 | ByteType | ByteType | |
| uint8 | ShortType | ShortType | |
| int16 | ShortType | ShortType | |
| uint16 | IntegerType | IntegerType | |
| int32 | IntegerType | IntegerType | |
| uint32 | LongType | LongType | |
| utf8 | StringType | StringType | |
| date | DateType | DateType | Arrow не поддерживается |
| datetime | DatetimeType | DatetimeType | Arrow не поддерживается |
| timestamp | TimestampType | TimestampType | Arrow не поддерживается |
| interval | LongType | LongType | Arrow не поддерживается |
| date32 | Date32Type | Date32Type | Кастомный тип SPYT расширенного диапазона (см. раздел ниже). Arrow не поддерживается |
| datetime64 | Datetime64Type | Datetime64Type | Кастомный тип SPYT расширенного диапазона (см. раздел ниже). Arrow не поддерживается |
| timestamp64 | Timestamp64Type | Timestamp64Type | Кастомный тип SPYT расширенного диапазона (см. раздел ниже). Arrow не поддерживается |
| interval64 | Interval64Type | Interval64Type | Кастомный тип SPYT расширенного диапазона (см. раздел ниже). Arrow не поддерживается |
| uuid | StringType | StringType | Arrow не поддерживается |
| json | StringType | StringType | Arrow не поддерживается |
| void | NullType | NullType |
Составные типы
В обозначениях ниже inner, key, value — типы вложенных элементов. Для каждого из них применяются правила «внутреннего уровня» (например, float → DoubleType).
| Тип YTsaurus | Сопоставление с типом Spark |
|---|---|
| Optional(inner) | inner тип с nullable = true |
| Dict(key, value) | MapType(key_type, value_type, value.nullable), где key_type и value_type — Spark-типы ключа и значения, определённые по правилам внутреннего уровня |
| Array(inner) | ArrayType(inner_type, inner.nullable), где inner_type — Spark-тип элемента по правилам внутреннего уровня |
| Struct(fields) | StructType с соответствующими сопоставлениями полей |
| Tuple(elements) | StructType с полями, названными _1, _2 и т.д. |
| VariantOverStruct | StructType с полями, префиксованными _v и nullable = true |
| VariantOverTuple | StructType с полями, названными _v_1, _v_2 и т.д. и nullable = true |
Сопоставление типов при записи в YTsaurus
| Тип Spark | Тип YTsaurus | Примечания |
|---|---|---|
| NullType | null | |
| ByteType | int8 | |
| ShortType | int16 (или uint8 при использовании schema_hint) | См. пример ниже |
| IntegerType | int32 (или uint16 при использовании schema_hint) | |
| LongType | int64 (или uint32 при использовании schema_hint) | |
| StringType | string (или utf8/json/uuid при использовании schema_hint, или utf8 если stringToUtf8 включено) | |
| FloatType | float | |
| DoubleType | double | |
| BooleanType | boolean | |
| DecimalType | Decimal(precision, scale) | precision ограничена 35 |
| ArrayType | Array(inner) | |
| StructType (tuple) | Tuple(elements) | |
| StructType (variant) | VariantOverStruct/VariantOverTuple | |
| StructType | Struct(fields) | |
| MapType | Dict(key, value) | |
| BinaryType | binary | |
| DateType | date | |
| DatetimeType | datetime | |
| TimestampType | timestamp | |
| Date32Type | date32 | |
| Datetime64Type | datetime64 | |
| Timestamp64Type | timestamp64 | |
| Interval64Type | interval64 | |
| UInt64Type | uint64 | |
| YsonType | any | YsonType — кастомный тип SPYT (см. раздел ниже) |
Переопределение типа через schema_hint
Если стандартное сопоставление не подходит, можно явно указать целевой YTsaurus-тип через schema_hint.
df.write.schema_hint({"my_col": "uint8"}).yt("//path/to/table")
df.write.schemaHint(Map("my_col" -> YtLogicalType.Uint8)).yt("//path/to/table")
Кастомные типы SPYT
Перечисленные ниже типы не входят в стандартный Apache Spark — они предоставляются библиотекой SPYT.
Временны́е типы расширенного диапазона
В YTsaurus существуют два набора временны́х типов:
- Стандартные (
date,datetime,timestamp,interval) — беззнаковые целые; диапазон[1970-01-01, 2105-12-31]. - Широкие (
date32,datetime64,timestamp64,interval64) — знаковые целые (int32/int64); диапазон около 145 000 лет в прошлое и в будущее от Unix-эпохи.
Широкие типы появились позже стандартных и являются предпочтительными для данных, выходящих за пределы 1970–2105. В Spark им соответствуют кастомные типы SPYT: Date32Type, Datetime64Type, Timestamp64Type, Interval64Type.
Подробнее про устройство временны́х типов в YTsaurus см. в разделе Временны́е типы.
YsonType
YsonType — кастомный UDT (User Defined Type), хранящий данные в виде YSON-байтов.
- При чтении из YTsaurus: тип
any/yson→YsonType(расширенный режим) илиBinaryType(базовый режим). - При записи в YTsaurus:
YsonType→ типany.
Подробнее про работу с YsonType см. в разделах Python API и Scala API.