Как стать автором
Обновить

Комментарии 9

То, что я увидел дальше, было самым быстрым временем, которое я видел при многократном выполнении каждого запроса в таблице trips_mergetree_x3.

Надеюсь что он не кэш ch проверял

Не, кэш ch не может быть 2.449 секунды
Строго говоря, это нетипичная конфигурация для ClickHouse — мало данных (помещаются целиком в оперативку) и использование NVMe SSD. Особенно в случае, если в результате GROUP BY получается очень много различных значений, которые нужно мержить на принимающей стороне, такая конфигурация не имеет особого смысла. То есть, я не утверждаю, что так делать вообще нельзя, но действительно выгоды от ClickHouse в этом случае меньше. Плюс, насколько я помню, есть настройка, которая позволяет отключить финальный Merge результатов на принимающей стороне, и тогда latency тоже будет лучше. В любом случае, почти всегда при использовании Distributed даже если latency не уменьшается в несколько раз, нагрузка на сервера падает, что позволяет выдерживать большую нагрузку на запись и на чтение в кластере.

Эх… прочитав подобную поверхностную статью, я тоже сильно воодушевился кликхаусом пару месяцев назад, решив использовав ch, как историческую базу для нескольких миллиардов транзакций в денормализованном виде, которые до этого хранились в партиционированной таблице с clustered columnstore index в MSSQL.


В итоге мы провели тесты на сервере с 72 железными ядрами (которые отображаются, как 144 логических), почти топовым NVMe диском, 512ГБ памяти.


Первое впечатление, что ch это очень круто. Да, агрегационные запросы сразу задействуют все ядра с первой секунды выполнения. Тупые запросы типа тех, что есть в статье, летают.


Но вот стоит написать что-то типа a join a on..., как потребление процессора падает до 1 ядра, и ch пытается в лоб в 1 поток это все просчитать. Более того, даже килл долгоотрабатывающих запросов отрабатывает как-то рандомно, и не с первого раза. То есть, если (применительно к домену примера) считать вещи типа "найти кластер пассажиров, которые имеют как минимум 10 одинаковых поездок с одним из членов кластера", или "вычислить семейные пары — люди, которые с одного района выезжают, едут на разные работы, но потом могут оттуда поехать в условный ресторан вместе (и, понятное дело, найти не конкретные кейсы, а принять решение статистически)", то ch показывает просто отвратительные результаты там, где mssql без проблем делает честный map-reduce под капотом с репартишенгом, где это надо. Хотя, кто знает, может есть какие-то неизвестные и неописанные в доке тонкости настройки или хинтов, которые включают магию… А такие задачи реально возникают, когда надо заготовить сложные фичи для ML, или искать кейсы фрода.


Из плюсов. Диалект SQL поражает некой правильностью и очевидностью мысли (видя вещи вроде приблизительного каунта, самого встречаемого значения, семплирования из коробки, неумножающего джойна, понимаешь что да, эти люди прямо залезли тебе в голову, и сделали то, чего давно подсознательно хотел). Но при этом, он лишен многих привычных вещей, и перестроить голову под сн — это непросто. Также есть прикольные административные фичи вроде ограничения памяти на юзера. Позволяет быстро отбивать бред типа джойнов с always true условием за несколько секунд.


Ну и, подводя итог, мы остались на mssql, принимая за ограничение, что о масштабировании выполнения больших аналитических запросов придется забыть (вертикально от 4 сокетов расти особо некуда — даже 8 сокетные системы на Xeon platinum уже неадекватно дороги, не говоря уже о монстрах вроде hp superdome x, а горизонтально не позволит mssql). Говоря же о сн, масштабирование тупых групбай по трем столбцам не сильно интересно в принципе. Тот же ms это делает и так очень быстро на одном сервере, и замедление даже на порядок вполне терпимо. И да, Google big query в свое время произвел куда лучше впечатление. Хотя, уверен, что есть масса примеров бизнесов, где надо считать примитивные аггрегации на кластерах на десятки тысяч ядер, и для них сн намного проще и эффективнее, чем любые другие решения (hadoop, написание шардинга на клиенте, сверхдорогие проприетарные решения)...

> стоит написать что-то типа join a on
> колоночная база данных

Вы уверены, что у вас был денормализованный вид?

Для избежания join-ов в наш DWH на ClickHouse приходилось ради приемлемой денормализации докидывать данные, иногда полученные join'ами из боевой базы, иногда парсить логи, иногда даже лазить за данными в API к партнерам — еще до вставки в CH. Благо наполнение DWH было фоновой, относительно неприоритетной задачей, real-time там был не нужен.

Зато у аналитиков tableau просто летал.

Разумеется, что уверен)
a join a — это не опечатка. В данном случае цель не дополнить таблицу дополнительными полями, так, как все уже предварительно дополнено. Цель — работать с сильно отфильтрованным декартовым произведением всех данных на все данные.

Всё верно, ClickHouse не умеет в merge join (пока что?), но, при некотором желании, обычно всё же можно организовать данные таким образом, чтобы можно было их эффективно использовать в ClickHouse (т.е. учитывая, что например join всегда означает hash join с выполнением подзапроса в первую очередь). См. например habr.com/ru/company/vk/blog/445284 — изначально тоже было требование иметь полноценные джойны, но после реструктуризации схемы базы получилось обойтись без них и получить хорошую производительность.

Но да, ClickHouse это тоже лишь инструмент и нужно понимать, когда его можно использовать, а когда не стоит (например джойнить 2 больших таблицы по сути ClickHouse не может).

Если у вас данных действительно много и переделка структуры данных под ClickHouse будет дешевле, чем покупка железа (и софта), то оно того стоит. Иначе действительно, возможно, имеет смысл использовать другие решения вроде Exasol, BigQuery и т.д.
Что касается следующих кейсов:

вещи типа «найти кластер пассажиров, которые имеют как минимум 10 одинаковых поездок с одним из членов кластера», или «вычислить семейные пары — люди, которые с одного района выезжают, едут на разные работы, но потом могут оттуда поехать в условный ресторан вместе (и, понятное дело, найти не конкретные кейсы, а принять решение статистически)»


Здесь вы, вероятно, хотите делать джойн таблицы сам на себя на лету, и это действительно ClickHouse не умеет делать. Но это не значит, что задачу нельзя решить в рамках ClickHouse. Для этого зачастую можно обойтись GROUP BY и правильной вставкой данных. Например, есть схожая задача — найти взаимные переписки пользователей (переписка пользователей это условно кортеж <from_user_id, to_user_id, message>). В наивном решении нам нужно делать что-то вроде SELECT ... FROM messages AS m JOIN messages AS m2 ON m1.from_user_id = m2.to_user_id GROUP BY .... Это работать в ClickHouse будет очень плохо (действительно нужен map reduce в этом случае). Но если немного поменять условия задачи и учитывать то, как ClickHouse хранит данные, то неожиданно можно получить намного лучшее решение:

Для каждой переписки мы вставляем по две записи, добавляя новое поле («тип»: исходящее или входящее сообщение):

<from_user_id, to_user_id, message, «out»>
<to_user_id, from_user_id, message, «in»>

Теперь, чтобы получить взаимные переписки (при условии сортировки по <user_id1, user_id2>), достаточно написать что-то вроде такого:

SELECT user_id1, user_id2 FROM messages GROUP BY user_id1, user_id2 WHERE uniqUpTo(2)(message_type) = 2

Где 2 — это 2 разных типа message_type: «out» и «in».

Похожим способом можно группировать другие сущности. Безусловно, это работает не для 100% случаев, но часто этого достаточно.
Скажите, в чем проблема цены 8-сокетника, если лицензия SQL Server под него будет 1,5млн $?
Зарегистрируйтесь на Хабре, чтобы оставить комментарий