Форматы данных и алгоритмы сжатия

В данном разделе описываются поддерживаемые в YDB форматы данных, хранимых в S3, поддерживаемые алгоритмы сжатия и список поддерживаемых YQL типов для каждого формата данных.

Поддерживаемые форматы данных

Список поддерживаемых в YDB форматов данных приведен в таблице ниже.

Формат Чтение Запись
csv ✓
csv_with_names ✓ ✓
tsv_with_names ✓ ✓
json_list ✓ ✓
json_each_row ✓ ✓
json_as_string ✓
parquet ✓ ✓
raw ✓ ✓

Формат csv

Данный формат основан на формате CSV и отличается от csv_with_names тем, что в нём нет заголовка с названиями столбцов. Все строки файла трактуются как данные, а имена колонок берутся из схемы запроса в порядке их объявления в SCHEMA.

Примечание

Формат csv доступен только для чтения данных из S3. Запись в этом формате не поддерживается.

Пример данных (без строки заголовка):

1997,Man_1,Model_1,3000.00
1999,Man_2,Model_2,4900.00
Пример запроса
SELECT
    *
FROM external_source.path
WITH
(
    FORMAT = "csv",
    SCHEMA =
    (
        Year Int32,
        Manufacturer Utf8,
        Model Utf8,
        Price Double
    )
)

Результат выполнения запроса:

# Manufacturer Model Price Year
1 Man_1 Model_1 3000 1997
2 Man_2 Model_2 4900 1999

Формат csv_with_names

Данный формат основан на формате CSV. Данные размещены в колонках, разделены запятыми, в первой строке файла находятся имена колонок. В отличие от формата csv, где имена колонок берутся из схемы запроса и сопоставляются позиционно, в формате csv_with_names имена колонок читаются непосредственно из заголовочной строки файла и сопоставляются со схемой по именам.

Пример данных:

Year,Manufacturer,Model,Price
1997,Man_1,Model_1,3000.00
1999,Man_2,Model_2,4900.00
Пример запроса
SELECT
    *
FROM external_source.path
WITH
(
    FORMAT = "csv_with_names",
    SCHEMA =
    (
        Year Int32,
        Manufacturer Utf8,
        Model Utf8,
        Price Double
    )
)

Результат выполнения запроса:

# Manufacturer Model Price Year
1 Man_1 Model_1 3000 1997
2 Man_2 Model_2 4900 1999

Формат tsv_with_names

Данный формат основан на формате TSV. Данные размещены в колонках, разделены символами табуляции (код 0x9), в первой строке файла находятся имена колонок.

Пример данных:

Year    Manufacturer    Model   Price
1997    Man_1   Model_1    3000.00
1999    Man_2   Model_2    4900.00
Пример запроса
SELECT
    *
FROM external_source.path
WITH
(
    FORMAT = "tsv_with_names",
    SCHEMA =
    (
        Year Int32,
        Manufacturer Utf8,
        Model Utf8,
        Price Double
    )
)

Результат выполнения запроса:

# Manufacturer Model Price Year
1 Man_1 Model_1 3000 1997
2 Man_2 Model_2 4900 1999

Формат json_list

Данный формат основан на JSON-представлении данных. В этом формате внутри каждого файла должен находиться объект в корректном JSON-представлении.

Пример корректных данных (данные представлены в виде списка объектов JSON):

[
    { "Year": 1997, "Manufacturer": "Man_1", "Model": "Model_1", "Price": 3000.0 },
    { "Year": 1999, "Manufacturer": "Man_2", "Model": "Model_2", "Price": 4900.00 }
]

Пример НЕкорректных данных (на каждой отдельной строке находится отдельный объект в формате JSON, но эти объекты не объединены в список):

{ "Year": 1997, "Manufacturer": "Man_1", "Model": "Model_1", "Price": 3000.0 }
{ "Year": 1999, "Manufacturer": "Man_2", "Model": "Model_2", "Price": 4900.00 }
Пример запроса
SELECT
    *
FROM external_source.path
WITH
(
    FORMAT = "json_list",
    SCHEMA =
    (
        Year Int32,
        Manufacturer Utf8,
        Model Utf8,
        Price Double
    )
)

Результат выполнения запроса:

# Manufacturer Model Price Year
1 Man_1 Model_1 3000 1997
2 Man_2 Model_2 4900 1999

Формат json_each_row

Данный формат основан на JSON-представлении данных. В этом формате внутри каждого файла на каждой отдельной строке файла должен находиться объект в корректном JSON-представлении, но эти объекты не объединены в JSON-список. Такой формат используется при передаче данных через потоковые системы, например, Apache Kafka или Топики YDB.

Пример корректных данных (на каждой отдельной строке находится отдельный объект в формате JSON, но эти объекты не объединены в список):

{ "Year": 1997, "Manufacturer": "Man_1", "Model": "Model_1", "Price": 3000.0 },
{ "Year": 1999, "Manufacturer": "Man_2", "Model": "Model_2", "Price": 4900.00 }
Пример запроса
SELECT
    *
FROM external_source.path
WITH
(
    FORMAT = "json_each_row",
    SCHEMA =
    (
        Year Int32,
        Manufacturer Utf8,
        Model Utf8,
        Price Double
    )
)

Результат выполнения запроса:

# Manufacturer Model Price Year
1 Man_1 Model_1 3000 1997
2 Man_2 Model_2 4900 1999

Формат json_as_string

Данный формат основан на JSON-представлении данных. Формат json_as_string не разбивает входной JSON-документ на поля, а представляет каждую строку файла в виде одного объекта JSON (или одной строки). Такой формат удобен, если список полей не одинаков во всех строках, а может изменяться.

В этом формате внутри каждого файла должен находиться:

  • объект в корректном JSON-представлении в каждой отдельной строке файла;
  • объекты в корректном JSON-представлении, объединенные в список.

Пример корректных данных (данные представлены в виде списка объектов JSON):

{ "Year": 1997, "Attrs": { "Manufacturer": "Man_1", "Model": "Model_1" }, "Price": 3000.0 }
{ "Year": 1999, "Attrs": { "Manufacturer": "Man_2", "Model": "Model_2" }, "Price": 4900.00 }

В этом формате схема читаемых данных должна состоять только из одной колонки с одним из разрешённых типов данных, подробнее см. ниже.

Пример запроса
SELECT
    CAST(JSON_VALUE(Data, "$.Year") AS Int32) AS Year,
    JSON_VALUE(Data, "$.Attrs.Manufacturer") AS Manufacturer,
    JSON_VALUE(Data, "$.Attrs.Model") AS Model,
    CAST(JSON_VALUE(Data, "$.Price") AS Double) AS Price
FROM external_source.path
WITH
(
    FORMAT = "json_as_string",
    SCHEMA =
    (
        Data Json
    )
)

Результат выполнения запроса:

# Manufacturer Model Price Year
1 Man_1 Model_1 3000 1997
2 Man_2 Model_2 4900 1999

Формат parquet

Данный формат позволяет считывать содержимое файлов в формате Apache Parquet.

Поддерживаемые алгоритмы сжатия данных внутри файлов Parquet для чтения из S3:

  • Без сжатия
  • SNAPPY
  • GZIP
  • BROTLI
  • LZ4
  • ZSTD
  • LZ4_RAW

Примечание

Запись в формате Parquet будет производится с использованием алгоритма сжатия Snappy.

Пример запроса
SELECT
    *
FROM external_source.path
WITH
(
    FORMAT = "parquet",
    SCHEMA =
    (
        Year Int32,
        Manufacturer Utf8,
        Model Utf8,
        Price Double
    )
)

Результат выполнения запроса:

# Manufacturer Model Price Year
1 Man_1 Model_1 3000 1997
2 Man_2 Model_2 4900 1999

Формат raw

Данный формат позволяет считывать содержимое файлов как есть, в "сыром" виде. Считанные таким образом данные можно обработать средствами YQL, разделив на строки и столбцы.

Этот формат стоит использовать, если встроенных возможностей парсинга исходных данных в YDB недостаточно. В этом формате схема данных для чтения и записи должна состоять только из одной колонки с одним из разрешённых типов данных, подробнее см. ниже.

Примечание

Размер каждого из считываемых файлов в формате raw не может превышать общего ограничения на потребление памяти одним запросом в YDB.

Пример запроса

Для парсинга следующих данных, где строки разделены точкой с запятой, а значения запятой:

1997,Man_1,Model_1,3000.00;
1999,Man_2,Model_2,4900.00;

Можно использовать запрос:

$input = SELECT
    String::SplitToList(        -- разделение каждой строки по ','
        String::Strip(RowData), -- удаление всех пробельных символов из начала и конца строк
        ","
    ) AS Row
FROM external_source.path
WITH
(
    FORMAT = "raw",
    SCHEMA =
    (
        FileData Utf8
    )
)
FLATTEN LIST BY (String::SplitToList(FileData, ";", TRUE AS SkipEmpty) AS RowData); -- разделение файла по ';'

SELECT -- Получение нужных колонок
    CAST(Row[0] AS Int32) AS Year,
    Row[1] AS Manufacturer,
    Row[2] AS Model,
    CAST(Row[3] AS Double) AS Price
FROM $input

Результат выполнения запроса:

# Manufacturer Model Price Year
1 Man_1 Model_1 3000 1997
2 Man_2 Model_2 4900 1999

Поддерживаемые алгоритмы сжатия

Использование алгоритмов сжатия зависит от форматов файлов. Для всех форматов файлов за исключением Parquet возможно использование следующих алгоритмов сжатия:

Алгоритм Название в YDB Чтение Запись
Gzip gzip ✓ ✓
Zstd zstd ✓ ✓
LZ4 lz4 ✓ ✓
Brotli brotli ✓ ✓
Bzip2 bzip2 ✓ ✓
Xz xz ✓ ✓

Для формата файлов Parquet поддерживаются собственные внутренние алгоритмы сжатия:

Формат сжатия Чтение Запись
Без сжатия ✓
Snappy ✓ ✓
Gzip ✓
Brotli ✓
LZ4 ✓
Zstd ✓
LZ4_RAW ✓

В YDB не поддерживается работа со сжатыми "снаружи" parquet-файлами, например, с файлами вида <myfile>.parquet.gz или аналогичными. Все файлы в формате Parquet должны быть без внешнего сжатия.

Поддерживаемые типы данных

Таблица всех поддерживаемых типов при чтении из S3 в схеме запроса:

Тип csv csv_with_names tsv_with_names json_list json_each_row json_as_string parquet raw
Bool,
Int8, Int16, Int32, Int64,
Uint8, Uint16, Uint32, Uint64,
Float, Double
✓ ✓ ✓ ✓ ✓ ✓
DyNumber ✓
String, Utf8, Json ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓
JsonDocument ✓
Yson ✓ ✓ ✓
Uuid ✓ ✓ ✓ ✓
Date, Datetime, Timestamp,
TzDate, TzDateTime, TzTimestamp
✓ ✓ ✓ ✓ ✓
Interval ✓ ✓ ✓ ✓ ✓
Date32, Datetime64, Timestamp64,
Interval64,
TzDate32, TzDateTime64, TzTimestamp64
✓
Optional<T> ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓

Таблица всех поддерживаемых типов при записи в S3:

Тип csv_with_names tsv_with_names json_list json_each_row parquet raw
Bool,
Int8, Int16, Int32, Int64,
Uint8, Uint16, Uint32, Uint64,
Float, Double
✓ ✓ ✓ ✓ ✓
DyNumber ✓
String, Utf8, Json ✓ ✓ ✓ ✓ ✓ ✓
JsonDocument
Yson ✓ ✓
Uuid ✓ ✓ ✓
Date, Datetime, Timestamp,
TzDate, TzDateTime, TzTimestamp
✓ ✓ ✓ ✓
Interval
Date32, Datetime64, Timestamp64,
Interval64,
TzDate32, TzDateTime64, TzTimestamp64
Optional<T> ✓ ✓ ✓ ✓ ✓

Для всех форматов чтения из S3 и записи в S3, кроме json_list, разрешено использовать тип Optional<T> только в том случае, если T — примитивный YQL тип. Подробнее об опциональных типах см. в статье column0.