Функции
В данном разделе собраны специфичные для CHYT функции.
Функции для работы с YSON
YPathType (простые типы и массивы)
YPath<Type>[Strict](yson, ypath) — извлечь из строки yson значение типа Type по пути ypath.
Type может принимать одно из следующих значений: Int64, UInt64, Boolean, Double, String, ArrayInt64, ArrayUInt64, ArrayBoolean, ArrayDouble.
Опциональный суффикс Strict обозначает строгость функции.
Примеры называний функций: YPathInt64, YPathStringStrict, YPathArrayDouble.
Принцип работы функций состоит в следующем:
- Переданная строка
ysonинтерпретируется как YSON-документ; - Происходит адресация в этом документе по пути
ypathотносительно корня документа; - Происходит интерпретация содержимого документа по пути
ypathк типуType.
На каждом из этапов работы данной функции могут возникнуть ошибки:
- Строка может не представлять собой YSON-документ (такое возможно при указании строковой константы в качестве аргумента функции, но не при чтении реальных Any-колонок из YTsaurus);
- Данный путь может отсутствовать в документе;
- Данный путь может соответствовать иному типу данных, отличному от
Type(например, вместо числового значения находится строковый литерал).
Отличие строгой версии функции (с суффиксом Strict) от нестрогой версии заключается в режиме обработки данных ошибок: строгая версия аварийно завершит работу запроса, тогда как нестрогая версия вернет в качестве результата значение по умолчанию для соответствующего типа колонки (Null, 0, пустую строку или пустой список) и продолжит работу.
Примеры использования (в качестве первого аргумента везде фигурирует строковый литерал, содержащий YSON, но на его месте может быть любая any-колонка таблицы):
SELECT YPathInt64('{key1=42; key2=57; key3=29}', '/key2');
57
SELECT YPathInt64('[3;4;5]', '/1');
4
SELECT YPathString('["aa";"bb";"cc"]', '/1');
"bb"
SELECT YPathString('{a=[{c=xyz}; {c=qwe}]}', '/a/1/c');
"qwe"
SELECT YPathInt64('{key=xyz}', '/key');
0
SELECT YPathInt64Strict('{key=xyz}', '/key');
std::exception. Code: 1001, type: NYT::TErrorException, e.what() = Node /key2 has invalid type: expected one of {"int64", "uint64"}, actual "string"
code 500
origin ...
SELECT YPathString('{key=3u}', '/nonexistentkey');
""
SELECT YPathArrayInt64('[1;2;3]', '');
[1, 2, 3]
SELECT YPathUInt64('42u', '');
42
Предположим, что в таблице есть две колонки lhs и rhs, представляющие собой any-колонки, содержащие списки чисел одинаковой длины.
Таблица 1 — Пример таблицы с any колонками
| lhs | rhs |
|---|---|
| [1, 2, 3] | [5, 6, 7] |
| [-1, 1] | [1, 3] |
| [] | [] |
Тогда можно построить скалярное произведение векторов lhs и rhs с помощью следующей конструкции:
SELECT arraySum((x, y) -> x*y, YPathArrayInt64(lhs, ''), YPathArrayInt64(rhs, '')) FROM "//path/to/table"
38
2
0
YPathExtract (сложные типы)
YPathExtract[Strict](yson, ypath, type) — извлечь из строки yson значение произвольного типа type по пути ypath.
Функция аналогична функциям YPath<Type>, но позволяет задать произвольный тип возвращаемого значения с помощью дополнительного аргумента type. Поддерживаются в том числе сложные составные типы, для которых нет аналога YPath<Type>.
Внимание
С помощью функции YPathExtract можно извлекать и простые типы. Например, результат выполнения YPathExtract(yson, ypath, 'Int64') будет эквивалентен результату YPathInt64(yson, ypath). Однако функции YPath<Type> более специализированы и имеют более оптимальную реализацию, поэтому рекомендуется использовать функцию YPathExtract только в случае, когда для извлекаемого типа нет специализированной функции.
Пример:
SELECT YPathExtract('[[1;2];[2;3]]', '', 'Array(Array(Int64))');
[[1, 2], [2, 3]]
SELECT YPathExtract('{a=1;b="abc"}', '', 'Tuple(a Int64, b String)');
("a": 1, "b": "abc")
SELECT YPathExtract('{x=["abc";"bbc"]}', '/x', 'Array(String)')
["abc", "bbc"]
YPathRaw (необработанный yson)
YPathRaw[Strict](yson, ypath, [format]) — извлечь из строки yson по пути ypath необработанное значение в формате yson.
Функция может быть применена, когда тип результируемого значения неизвестен, либо различается в разных строках одной колонки.
Опциональный параметр format позволяет задать формат представления возвращаемого yson значения и может быть одним из следующих: binary (по умолчанию), text, pretty, unescaped_text, unescaped_pretty.
Примеры:
SELECT YPathRaw('{x={key=[1]}}', '/x', 'text');
'{"key"=[1;];}'
SELECT YPathRaw('{a=1}', '/b', 'text');
NULL
Семейство функций YSON*
Для работы с форматом json в ClickHouse присутсвуют функции семейства JSON*. Для более схожей работы с обычным ClickHouse, в CHYT поддержаны полные аналоги этих функций, работающие с форматом yson.
Значение аргументов функций и их возвращаемое значение можно посмотреть в документации ClickHouse.
Поддержанные аналоги на данный момент:
YSONHas, YSONLength, YSONKey, YSONType, YSONExtractInt, YSONExtractUInt, YSONExtractFloat, YSONExtractBool, YSONExtractString, YSONExtract, YSONExtractKeysAndValues, YSONExtractRaw, YSONExtractArrayRaw, YSONExtractKeysAndValuesRaw.
Примечание
В отличие от функций YPath, в которых нумерация элементов в массиве начинается с 0, нумерация элементов в функциях YSON* c единицы.
Внимание
Данные функции реализованы общим с ClickHouse кодом и не являются оптимальными. Для ускорения вычислений на большом количестве данных рекомендуется воспользоваться более оптимальными функциями YPath<Type>.
Пример:
-- Эквивалентно YPathString('["aa";"bb";"cc"]', '/0')
-- Обратите внимание, нумерация начинается с 1
SELECT YSONExtractString('["aa";"bb";"cc"]', 1);
"aa"
-- Эквивалентно YPathString('{a=[{c=xyz}; {c=qwe}]}', '/a/1/c')
SELECT YSONExtractString('{a=[{c=xyz}; {c=qwe}]}', 'a', 2, 'c');
"qwe"
Форматы представления YSON
Данные из колонок типа any могут храниться в бинарном представлении yson. Поскольку читать такие данные не всегда удобно, в CHYT имеется функция ConvertYson, которая преобразует разные представления yson между собой.
ConvertYson(yson, format) — преобразовать строку с yson документом в указанный формат.
Всего существует пять возможных форматов представления:
binarytextprettyunescaped_text*unescaped_pretty*
* Примечание
В системе YTsaurus предусмотрено 3 формата представления — binary, text и pretty.
В форматах представления text и pretty в значениях строк экранируются все символы, выходящие за пределы ascii, в том числе кириллица и различные символы в кодировке utf-8. Чтобы результирующий yson, содержащий строки с символами кириллицы, был более человекочитаемым, в CHYT были добавлены два дополнительных формата - unescaped_text и unescaped_pretty. Эти форматы отличаются от text и pretty только тем, что в строковых значениях экранируются только служебные для формата yson символы. Остальные символы сохраняются в строках без изменений.
Примеры:
SELECT ConvertYson('{x=1}', 'text');
'{"x"=1;}'
SELECT ConvertYson('{x=1}', 'pretty');
'{
"x" = 1;
}'
SELECT ConvertYson('{x=1}', 'binary');
'{\u0001\u0002x=\u0002\u0002;}'
SELECT ConvertYson('{x="Пример"}', 'text');
'{"x"="\xD0\x9F\xD1\x80\xD0\xB8\xD0\xBC\xD0\xB5\xD1\x80";}'
SELECT ConvertYson('{x="Пример"}', 'unescaped_text');
'{"x"="Пример";}'
Пример работы с YSON
SELECT operation_id, task_id, YPathInt64(task_spec, '/gpu_limit') as gpu_limit, YPathInt64(task_spec, '/job_count') as job_count FROM (
SELECT tupleElement(tasks, 1) as task_id, tupleElement(tasks, 2) as task_spec, operation_id FROM (
SELECT operation_id, tasks FROM (
Select YSONExtractKeysAndValuesRaw(COALESCE(tasks, '')) as tasks, operation_id FROM (
SELECT YSONExtractRaw(spec, 'tasks') as tasks, operation_id
FROM `//home/dev/chyt_examples/completed_ops`
WHERE YSONHas(spec, 'tasks')
)
)
ARRAY JOIN tasks
)
)
ORDER BY gpu_limit DESC;
Получение версии клики
Получение версии CHYT
chytVersion() — получить строковое представление версии CHYT сервера.
Пример:
SELECT chytVersion()
Получение версии YTsaurus
ytVersion() — получить строковое представление версии кода YTsaurus, используемого в текущей версии CHYT.
Пример:
SELECT ytVersion()
Работа с кипарисом
Примечание
Все функции для работы с кипарисом являются табличными в терминах ClickHouse. Это означает, что их возвращаемое значение может использоваться вместо таблицы, например, в секции FROM запроса SELECT.
ytListNodes
ytListNodes[L](dir_path, [from, [to]]) — получить список всех узлов и их атрибутов в директории dir_path.
Результат содержит по одной строке на каждый узел из директории dir_path. Каждая строка содержит:
-
Две встроеных колонки
$keyи$path, хранящие имя и полный путь до узла (всегда начинается сdir_path). Значение в данных колонках могут отличаться от атрибутовkeyиpath, если узел является ссылкой (типlink) на другой узел. -
3 колонки, соответствующие полям атрибута
resource_usage:disk_space,tablet_countиmaster_memory. -
Большое количество колонок, название которых соответствует названию атрибута узла:
key,path,account,owner,erasure_codec,id,aclи другие. Колонки включают практически все системные атрибуты.
Примечание
Так как обычно пользователям не нужны все атрибуты узла, большинство колонок являются виртуальными в терминах ClickHouse. Это означает, что по умолчанию они не возвращаются через выражения SELECT * FROM ytListNodes(...) и DESCRIBE ytListNodes(...), но могут быть запрошены явно:
SELECT id, key_columns, * FROM ytListNodes(...)
По умолчанию функция ytListNodes не раскрывает ссылки (узлы типа link). Это означает, что для таких узлов в результате будут возвращены атрибуты самого узла ссылки, а не узла, на который она ссылается. Что бы изменить это поведение и раскрыть все ссылки, можно воспользоваться модификатором функции L (ytListNodesL). При этом если ссылка ведет в несуществующий узел, то она останется нераскрытой, поэтому в результате все равно могут присутсвовать строки с типом link, соответствующие нераскрытым ссылкам.
Внимание
Раскрытие каждой ссылки требует дополнительного запроса к мастер серверу, поэтому исполнение функции ytListNodeL может быть дольше и ресурсозатратнее, чем ytListNode. Использование ytListNodeL для директорий с большим количеством ссылок крайне не рекомендуется.
С помощью двух опциональных строковых аргументов from и to можно задать фильтрацию возвращаемых узлов по названию (колонке $key). Сравнение лексикографическое.
Пример:
SELECT * FROM ytListNodes('//some/dir/path');
SELECT sum(disk_space), sum(chunk_count) FROM ytListNodes('//some/dir/path');
SELECT * FROM ytListNodesL('//some/dir/path');
ytListTables
ytListTables[L](dir_path, [from, [to]]) — получить список всех таблиц и их атрибутов в директории.
Аргументы функции и структура возвращаемого значения аналогичны функции ytListNodes[L].
Рузультат функции эквивалентен результату вызова ytListNodes[L] с последующей фильтрацией WHERE type = 'table'.
Суффикс L имеет аналогичное значение и расскрывает все ссылки перед фильтрацией. Таким образом, результат выполнения ytListTables будет содержать только таблицы, непосредственно находящиеся в указанной директории, а результат выполнения ytListTablesL будет дополнительно содержать таблицы, на которые указывают ссылки из указанной директории.
SELECT path, chunk_count FROM ytListTables('//dome/dir/path');
ytListLogTables
ytListLogTables(project_name_or_path, [from_datetime, [to_datetime]]) — получить непересекающийся по времени список таблиц с логами и их атрибуты из указанного проекта.
project_name_or_path может содержать либо название проекта с логами (если проект лежит в директории //logs), либо полный путь до директории с логами.
Функция рассмотрит таблицы с логами в четырех поддиректориях (1h, 30m, 1d и stream/5m), после чего объединит множества этих таблиц так, что бы интервалы времени таблиц не пересекались.
С помощью двух опциональных аргументов from_datetime и to_datetime можно задать интересующий временной интервал логов. Таблицы с логами, которые не пересекаются по времени с указанным интервалом, будут отфильтрованы.
Примечание
Фильтрация по временному интервалу происходит только на уровне таблиц. Таблицы с логами из результата работы функции могут покрывать больший временной интервал, чем указанный в аргументах.
Пример:
SELECT * FROM ytListLogTables('chyt-structured-http-proxy-log', today() - 1);
SELECT * FROM ytListLogTables('//logs/chyt-structured-http-proxy-log', today() - 5, today() - 4);
ytNodeAttributes
ytNodeAttributes(path1, [path2, [...]]) — получить атрибуты всех узлов, указанных в аргументах.
Возвращаемое значение будет содержать по 1 строке с атрибутами на каждый указанный в аргументах путь. Если указан некоректный или несуществующий путь, будет сгенерирована ошибка.
Структура возвращаемого значения аналогична функции ytListNodes.
Пример:
SELECT * FROM ytNodeAttributes('//sys', '//sys/clickhouse')
Чтение множества таблиц
Примечание
Все функции для чтения множества таблиц являются табличными в терминах ClickHouse. Это означает, что их возвращаемое значение может использоваться вместо таблицы, например, в секции FROM запроса SELECT.
ytTables
ytTables(arg1, [arg2, ...]) — прочитать объединение множества таблиц, указанного в аргументах.
Каждый аргумент может быть одним из следующих:
- Строка, представляющая собой путь до конкретной таблицы
- Одна из функций
ytListNodes[L],ytListTables[L],ytListLogTables - Подзапрос, возвращающий произвольное множество путей таблиц*
* Внимание
Передача в качестве аргумента функции подзапроса, возвращающего несколько путей, не соответствует синтаксису ClickHouse. Данная конструкция работает в текущей версии CHYT/ClickHouse, но может перестать работать в будущих версиях. Более правильным способом передачи такого подзапроса является использование функции view.
Также на данный момент известно о баге оптимизатора ClickHouse, который может некоретно переносить внешнее условие WHERE внутрь такого подзапроса, в результате чего может возникать ошибка Missing columns: '<column_name>' while processing query. Обойти данную ошибку можно с помощью настройки enable_optimize_predicate_expression=0.
Функция возвращает объединение множества всех таблиц, заданных в аргументах. Работа функции аналогичная функции merge из ClickHouse, но она предоставляет более гибкую систему указания множества таблиц и оптимизирована для работы с таблицами YTsaurus.
Если таблицы из заданного множества таблиц имеют различные схемы, то будет выведена общая схема, с помощью которой можно прочитать все заданные таблицы.
Алгоритм вывода общей схемы
Совместимые типы
- Для каждой колонки выбирается "наиболее общий тип", к которому можно привести все типы.
- Пример: для типов
optional<int32>иint64"наиболее общим типом" будетoptional<i64>. - Обратите внимание, что ввиду особенностей хранения данных в YTsaurus, беззнаковые числовые типы являются несовместимыми со знаковыми (т.е. типы
int32иuint32несовместимы).
Несовместимые типы
- Если типы колонки несовместимы в разных таблицах, то chyt будет действовать согласно опции
chyt.concat_tables.type_mismatch_mode. - Пример: типы
stringиint64несовместимы. - Возможные значения опции:
drop,throw,read_as_any. - По умолчанию произойдет ошибка исполнения запроса (значение
throw). - Колонки разных типов можно прочитать как yson-строки, указав значение опции
read_as_any. Это может быть неэффективно, поэтому рекомендуется структурировать свои таблицы правильно. - Если такие колонки не нужны для исполнения запроса, их можно отбросить, указав значение опции
drop.
Отсутствующая колонка
- Если колонка отсуствует в одной или в нескольких входных таблицах, то chyt будет действовать согласно опции
chyt.concat_tables.missing_column_mode. - Возможные значения:
drop,throw,read_as_null. - По умолчанию колонка станет опциональной, а значения из таблиц, где колонка пропущена, будут прочитаны как
NULL(значениеread_as_null). - Если отсутствие колонок в некоторых таблицах неожидаемо, в таком случае можно генерировать ошибку исполнения запроса, указав значение опции
throw. - Как и в случае с несовместимыми типами, такие колонки можно отбросить, указав значение опции
drop. - Обратите внимание, опция
missing_column_modeвлияет на поведение только в случае, если колонка пропущена в таблице со строгой схемой. Если колонка пропущена в нестрогой схеме, то она все равно может существовать в самих данных с любым типом. В этом случае делается пессимистичное предположение, что колонка присутствует с несовместимым типом, и дальнейшее поведение регулируется описанной ранее опциейtype_mismatch_mode.
Примечание
Помимо основных колонок из самих таблиц в результате также всегда присутсвуют виртуальные колонки $table_index, $table_name и $table_path. С помощью данных колонок можно определить, из какой именно таблицы была прочитана каждая строчка. Подробнее про виртуальные колонки можно прочитать в соответствующем разделе.
Пример:
-- Прочитать объединение 2 таблиц:
SELECT * FROM ytTables('//tmp/t1', '//tmp/t2')
-- Прочитать объединение всех таблиц из директории '//tmp/dir':
SELECT * FROM ytTables(ytListTables('//tmp/dir'))
-- Прочитать объединение всех таблиц из директории и их названия:
SELECT *, $table_name FROM ytTables(ytListTables('//tmp/dir'))
-- Прочитать последнюю (лексикографически) таблицу:
SELECT * FROM ytTables((
SELECT max(path) FROM ytListTables('/tmp/dir')
))
-- Прочитать таблицы с определенным суффиксом:
SELECT * FROM ytTables((
SELECT concat(path, '/suffix') FROM ytListNodes('//tmp/dir')
))
concatYtTables
concatYtTables(table1, [table2, [...]]) — прочитать объединение нескольких YTsaurus таблиц.
Устаревший вариант функции ytTables. В качестве аргументов могут выступать только пути таблиц.
Пример:
SELECT * FROM concatYtTables('//tmp/sample_table', '//tmp/sample_table2');
concatYtTablesRange
concatYtTablesRange(cypress_path, [from, [to]]) — прочитать объединение всех таблиц из директории cypress_path.
Устаревшая функция, эквивалентная ytTables(ytListTables(cypress_path, from, to)).
Пример:
SELECT * FROM concatYtTablesRange("//tmp/sample_tables");
SELECT * FROM concatYtTablesRange('//tmp/sample_tables', '2019-01-01');
SELECT * FROM concatYtTablesRange('//tmp/sample_tables', '2019-08-13T11:00:00');