Форматы данных Template и Regexp. Ускорение batch insert с вычислимыми выражениями путём вывода шаблонов

Материал из Wiki - Факультет компьютерных наук
Перейти к: навигация, поиск
Компания Яндекс
Учебный семестр Осень 2018
Учебный курс 3-4-й курс
Максимальное количество студентов, выбравших проект: ?



Многие текстовые форматы данных определяются лишь тем, каким образом в них записаны значения (с каким экранированием) и какие разделители используются между значениями и строками. Предлагается реализовать формат Template, который выводит или считывает данные по указанному шаблону. Шаблон представляет собой строку с подстановками, где подстановка - это имя столбца и способ его записи. Например:

Title is ${Title:JSON} - этот шаблон выведет (или прочитает) ""Title is"", а затем поле Title в двойных кавычках, с экранированием так же, как в JSON.

В качестве бонуса предлагается реализовать также формат Regexp. Этот формат предназначен для чтения входных данных. Над строкой входных данных применяется указанный регексп, а значения столбцов заполняются из соответствующих match-ей. Это позволит использовать программу clickhouse-local так же как awk.

В ClickHouse есть формат данных Values. Он используется, когда пользователь отправил обычный запрос INSERT INTO table ... VALUES ... Пример: INSERT INTO table (num, str) VALUES (123, 'Hello'), (456, 'World').

Для разбора такого формата обычно используется быстрый потоковый парсер. Но проблема в том, что вместо значений, в запросе могут быть указаны произвольные выражения: INSERT INTO table (num, str) VALUES (12 + 3, concat('Hello', 'world')).

Быстрый потоковый парсер не может интерпретировать выражения. Поэтому в ClickHouse реализован fallback на медленный парсер. Но проблема в том, что ClickHouse оптимизирован на вычисления над целыми массивами, тогда как вычисления над отдельными значениями, в нём работают очень неэффективно. То есть, парсер, вычисляющий выражения по отдельности, работает очень медленно.

Тем не менее, можно заметить, что в случае наличия выражений, их структура обычно одинаковая в каждой строке: INSERT INTO table (num, str) VALUES (now(), toDate('2000-01-01'), 123 + 456), (now(), toDate('2001-01-01'), 789 + 100).

Можно попробовать составить шаблон по первой строке: (now(), toDate(?), ? + ?) и оптимистично применять его для парсинга остальных строк.

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