ClickHouse: стриминг для бедных
достался в поддержку проект по реалтайм обработке данных на основе КХ — чем больше в него погружаюсь, тем больше он нравится!
смысл простой: из брокера сообщений инсёртим данные в КХ и там через материализованные представления раскладываем их в одну широкую денормализованную витрину.
на выходе получаем основные данные для аналитики бизнеса с задержкой в единицы секунд для основных атрибутов и доезд остальных по мере поступления.
вообще Кликхаус мне представляется как кладезь интересных технических решений. По мере погружения проект отметил два пункта, почему такой проект в принципе работает:
1. колоночное хранение
2. движки таблиц семейства MergeTree
3. матвьюхи, работающие по принципу стриминга
1/ колоночное хранение
данные в таблицах базы — это файлы на диске (довольно очевидно, но до меня это дошло только когда читал Кабанчика)
Когда в одном файле лежат полные строки, то в них могут быть нуллы, т.е. лишняя информация. Если хранение повернуть на 90° и хранить в файлах колонки, то там ничего лишнего не будет; а дополнительно получаешь плюшки в виде более эффективного сжатия и аналитических запросов.
И тогда мы можем инсёртить в нашу широкую витрину на 100+ атрибутов из разных загрузчиков — каждый загрузчик наполняет только своё подмножество атрибутов. При такой вставке в остальных атрибутах не прорастают лишние нуллы.
Чем-то похоже на принцип загрузки в анкор-датаволт: у нас есть «хаб» с первичным ключом и набор отдельных атрибутов-сателлитов; только не на уровне таблиц в базе, а на уровне файлов на диске.
2/ таблицы MergeTree
ещё в Кабанчике читал про разницу между разными методами хранения данных в базе данных: B-Tree и LSM Tree.
B-Tree хранит данные в дереве — это очень удобно для чтения, потому что можно до любой ячейки дойти за пару шагов по этому дереву. Но записывать такое дерево сложно — перед записью надо найти конкретное место, куда положить твои байтики. А если лист дерева переполнен, нужно создать новый.
Log-Structered Merge (LSM) Tree же наоборот оптимизирует запись. Все входящий байтики пишутся тупо в конец последнего файла. Это очень быстро для записи.
Но читать такое сложно — при доступе по ключу записи надо проверить все файлы от последнего к первому (самые плохие кейсы, когда такого ключа нет).
В ClickHouse есть целое семейство из движков таблиц — MergeTree, поэтому туда можно быстро и много инсёртить. А под капотом уже происходит merge — наваленные в порядке записи файлики раскладываются в сортированном порядке, удаляя лишние данные. Что позволяет читать ваши терабайты за секунды.
3/ «стриминг» матвью
интересная особенность матвьюх в КХ — они «присоединяются» к таблице-источник и их логика трансформации применяется к каждому входящему в эту таблицу куску данных.
благодаря этой особенности можно налету «парсить» прилетающие из брокера сообщений инсёрты и раскладывать в нужные колонки нашей широкой витрины.
напоминает триггеры из других баз — типа на каждый инсерт в таблицу Т1 делаем набор действий с таблицами Т2..Т99.
И тут история делает полный круг — на первом своём проекте по дох-строению я сделал условный ЕТЛ на триггерах внутри Постгрес (про Эйрфлоу я тогда ещё не знал =). Как прототип это работало, но развивать и поддерживать это было сложно.
В самом КХ это поддерживать тоже трудновато, надо запросы и DDL выносить куда-то во вне. Но по крайней мере оно всё работает на продавшен объёмах и не загибается; подозреваю, что благодаря пунктам 1. и 2. (и техническому гению Алексея Миловидова и команды КХ)
Post #312
1.04K