Описание
HiveText читает и записывает формат текстовой сериализации, используемый таблицами
Apache Hive (формат, создаваемый LazySimpleSerDe
в Hive). Это текстовый формат с разделителями, похожий на CSV, в котором поля
разделяются стандартным для Hive разделителем \x01 (Ctrl-A). Разделитель полей
можно настроить через input_format_hive_text_fields_delimiter.
При использовании в качестве входного формата у данных нет строки заголовка: значения
сопоставляются со столбцами целевой таблицы по позиции, поэтому имена столбцов и типы
берутся из таблицы (или из явно заданной
структуры), а не определяются автоматически по данным. При чтении ClickHouse разбирает
даты и время в режиме best-effort (см. date_time_input_format),
заполняет пропущенные конечные поля значениями по умолчанию для столбцов и пропускает поля, которые не
распознаёт.
Внутри поля значения разбираются по тем же правилам экранирования, что и в CSV, а не
с использованием вложенных разделителей Hive. В частности, столбец типа
Array читается из представления
в квадратных скобках (например, "['a','b','c']"), а не из значений, разделённых
разделителем коллекции Hive \x02.
Настройки вложенных разделителей не влияют на вводНастройки
input_format_hive_text_collection_items_delimiter и
input_format_hive_text_map_keys_delimiter
принимаются для совместимости, но в настоящее время не используются при разборе. Однако
они используются при записи вложенных значений.input_format_hive_text_allow_variable_number_of_columns):
в строках, где полей меньше, чем в таблице, отсутствующие столбцы заполняются
значениями по умолчанию, а в строках с лишними конечными полями лишние поля пропускаются.
Пример использования
,) с помощью
input_format_hive_text_fields_delimiter, чтобы входные
файлы было удобнее читать.
Чтение файла в формате HiveText
hive_data.txt с полями, разделёнными запятыми:
hive_data.txt
FORMAT HiveText:
Query
Response
1,3 содержит только два поля, поэтому отсутствующий столбец c
заполняется значением по умолчанию 0.
Переменное количество столбцов
input_format_hive_text_allow_variable_number_of_columns = 1
у строк, содержащих больше полей, чем предусмотрено в таблице, лишние поля в конце
просто пропускаются:
hive_extras.txt
Query
Response
input_format_hive_text_allow_variable_number_of_columns = 0 вместо этого
требует строгого количества полей, и если в строке полей меньше, чем в таблице, возникает
исключение при разборе.
Вывод
HiveText записывает каждую строку без экранирования:
поля верхнего уровня разделяются разделителем полей (по умолчанию \x01), а
строки — разделителем строк (по умолчанию \n, настраивается с помощью
format_hive_text_rows_delimiter). Значения вложенных типов
(Array, Map
и Tuple) записываются без скобок и
разделяются разделителем Hive соответствующего уровня вложенности — так же, как в
LazySimpleSerDe Hive. Первые три разделителя: настраиваемый разделитель
полей, input_format_hive_text_collection_items_delimiter
(по умолчанию \x02, используется для элементов массива, записей map и элементов кортежа) и
input_format_hive_text_map_keys_delimiter (по умолчанию \x03,
используется между ключом map и его значением); для более глубоких уровней по умолчанию используются последовательные управляющие
символы (\x04, \x05 и так далее, до восьми уровней). Дерево типов с
достаточно глубокой вложенностью, которому требуется разделитель за пределами этих восьми уровней, отклоняется с
исключением NOT_IMPLEMENTED, поскольку в LazySimpleSerDe Hive также нет разделителя для
него. Типы данных, не имеющие естественного
текстового представления в Hive, не поддерживаются для вывода и вызывают
исключение NOT_IMPLEMENTED. К ним относятся AggregateFunction, Dynamic,
Variant, LowCardinality и Object, а также числовые типы
Enum, Time, Time64 и Interval — в Hive нет соответствующих типов для
последних, поэтому они отклоняются, а не записываются как исходные базовые
числа. Числовые типы большой разрядности Int128, UInt128, Int256 и UInt256
отклоняются по той же причине: самый широкий целочисленный тип Hive — BIGINT (64-битный),
и даже DECIMAL Hive с максимальной точностью 38 не может вместить весь их
диапазон значений. Аналогично, значения Decimal с точностью выше 38 (то есть
Decimal256) превышают максимальную точность DECIMAL Hive и отклоняются.
Также ключи Map должны иметь примитивный тип: Hive объявляет map
как MAP<primitive_type, data_type>, поэтому Map с типом ключа Array,
Map или Tuple (что допускает ClickHouse) отклоняется с
исключением NOT_IMPLEMENTED, поскольку ни одна схема Hive не смогла бы прочитать такие значения
обратно. Пустой литерал map map() отклоняется по той же причине: его тип —
Map(Nothing, Nothing), а Nothing не является типом, который мог бы быть указан в объявлении Hive
MAP<key_type, data_type>. Все эти проверки применяются заранее к объявленным типам столбцов, до
записи любой строки: запрос, заголовок которого содержит неподдерживаемый тип в любом месте
дерева типов, отклоняется, даже если фактические значения никогда не достигли бы
неподдерживаемой сериализации (например, Nullable неподдерживаемого типа,
содержащий только значения NULL, или пустой Array/Map с неподдерживаемым типом элемента),
поскольку объявленная схема файла всё равно не могла бы соответствовать ни одной таблице Hive.
Date, Date32, DateTime и DateTime64 всегда записываются в обычном
текстовом формате даты и временной метки Hive (yyyy-MM-dd и yyyy-MM-dd HH:mm:ss[.fffffffff]),
независимо от настройки date_time_output_format,
чтобы вывод оставался доступным для разбора в Hive, даже если эта настройка имеет значение
unix_timestamp или iso.
По той же причине значения Bool всегда записываются как true/false,
независимо от настроек bool_true_representation
и bool_false_representation,
а значения NULL всегда записываются как используемая Hive по умолчанию null-последовательность
\N, независимо от настройки format_csv_null_representation.
Благодаря этому вывод остаётся читаемым для LazySimpleSerDe Hive независимо от
этих общих текстовых настроек. Аналогично, входной формат HiveText всегда
интерпретирует \N как NULL, также независимо от настройки
format_csv_null_representation,
поэтому цикл записи и чтения скаляров верхнего уровня от неё не зависит.
Неконечные значения Float32 и Float64 записываются с использованием Java-обозначений Hive
NaN, Infinity и -Infinity, а не обычных для ClickHouse токенов nan/inf/-inf,
чтобы парсер Hive для FLOAT/DOUBLE считывал их как те же значения,
а не как NULL.
Вывод, совместимый с Hive, а не полноценный цикл записи и чтения через входной форматВывод ориентирован на используемый в Hive по умолчанию
LazySimpleSerDe и не симметричен
собственному входному формату HiveText ClickHouse:- Вложенные значения
Array,MapиTupleзаписываются с использованием вложенных разделителей Hive (без скобок), но входной формат разбирает каждое поле по правиламCSV/со скобками и игнорируетinput_format_hive_text_collection_items_delimiter/input_format_hive_text_map_keys_delimiter. Поэтому вложенный вывод, напримерSELECT [1, 2] FORMAT HiveText, не считывается обратно с помощьюINSERT ... FORMAT HiveText— цикл записи и чтения поддерживается только для скалярных полей верхнего уровня и только с разделителем строк по умолчанию\n(см. следующий пункт). - Для цикла записи и чтения также требуется разделитель строк по умолчанию
\n. При измененииformat_hive_text_rows_delimiterвывод разделяет строки настроенным байтом, но на входе по-прежнему используетсяCSVRowInputFormat, основанный на переводах строк, и соответствующий параметрinput_format_hive_text_rows_delimiterотсутствует. Поэтому многострочный скалярный вывод, напримерSELECT number FROM numbers(3) FORMAT HiveText SETTINGS format_hive_text_rows_delimiter=';'(который создаёт0;1;2;), не считывается обратно черезINSERT ... FORMAT HiveTextкак три строки. - Реализовано только используемое по умолчанию подмножество
LazySimpleSerDeбез экранирования. Поля записываются без экранирования (нет эквивалента необязательного параметра HiveROW FORMAT DELIMITED ... ESCAPED BY), аNULLвсегда записывается как\N(нет эквивалентаNULL DEFINED AS). ПоэтомуString, содержащая активный разделитель поля, строки или вложенных значений, записывается буквально и при последующем разборе будет прочитана неверно — это соответствует поведению самого Hive с serde без экранирования. По той же причинеString, значение которой буквально равно\N(например,SELECT '\\N'::String FORMAT HiveText), записывается теми же двумя байтами, что и настоящийNULL, поэтому на стороне Hive их невозможно различить.
Query