Skip to content

Instantly share code, notes, and snippets.

@alexey-milovidov
Created December 19, 2018 19:54
Show Gist options
  • Select an option

  • Save alexey-milovidov/5551a7c7b7aba731a0a74f01972ddc69 to your computer and use it in GitHub Desktop.

Select an option

Save alexey-milovidov/5551a7c7b7aba731a0a74f01972ddc69 to your computer and use it in GitHub Desktop.
Поддержка Protobuf как формата ввода-вывода для ClickHouse.
ClickHouse поддерживает всевозможные форматы данных для получения результата запроса SELECT или для загрузки данных при INSERT. К этим форматам относятся как текстовые (CSV, TSV, JSONEachRow) так и бинарные (RowBinary, Native).
Пользователи хотят иметь в качестве доступного формата ещё и Protobuf.
Формат представляет собой записанные подряд Protobuf сообщения, по одному на каждую строку таблицы, разделённые неким общепринятым способом: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/util/delimited_message_util.h
Пользователь может предоставить свою protobuf схему для загрузки и выгрузки данных. Это определяется настройкой format_schema (по аналогии с имеющимся форматом CapNProto). При этом, схема может более-менее свободно относиться к таблице. Так, один тип данных ClickHouse может быть по-разному представлен в protobuf схеме. Например, UInt8 в ClickHouse может быть int64 в Protobuf. String может быть представлен и как string и как bytes. DateTime может быть представлена и как string и как int.
Впрочем, есть некоторые ограничения. Массивы - repeated поле. Многомерные массивы не поддерживаются. Вложенные Message не поддерживаются. Ещё не знаю, что выбрать для Enum. DateTime - uint32, Date - UInt16. String, FixedString - string или bytes. AggregateFunction - bytes. Nullable - optional. Для целей простоты реализации, не поддерживаются случаи, когда значения repeated полей в сериализованном protobuf идут не подряд.
Предлагается сделать в IDataType методы deserializeProtobuf, serializeProtobuf, которые также принимают аргумент - в каком protobuf типе находится значение, и содержать switch-case внутри.
Впрочем, предусматривается и работа без указания protobuf схемы. В этом случае, данные будут записываться в некоторой канонической схеме, которую ClickHouse выбирает сам из их структуры. И, соответственно, считываться в этом, ожидаемом формате. В каноническом формате, впрочем, все поля optional - на всякий случай.
Если protobuf сообщение не содержит некоторого поля, то при чтении, вычисляются значения по-умолчанию, по аналогии с форматом JSONEachRow. (Значение NULL может быть считано только как значение по-умолчанию.)
Для сериализации/десериализации, из библиотеки protobuf используется работа с метаданными, но не с самими объектами-сообщениями. Сериализация/десериализация отдельных полей идёт "вручную". Для size-delimited формата можно использовать лишнее копирование в первом варианте реализации.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment