Эта запись в основном представляет из себя мои упорядоченные рабочие заметки и имеет достаточно прикладное значение, так что не стоит ожидать от неё каких-либо откровений. Тем не менее, буду рад, если написанное здесь кому-нибудь пригодится.
Итак, несколько недель назад я добрался до стремительно набирающей популярность СУБД ClickHouse (далее CH). За это время слегка разобрался, как её готовить и сейчас расскажу о своём опыте.
Для начала - что это такое и чем оно отличается от аналогов? CH - СУБД аналитическая (OLAP) столбцовая СУБД, т.е. область её применения довольно узкая и не стоит думать о ней как об универсальной СУБД - далеко не всегда ей можно будет заменить какой-нибудь MySQL или MongoDB. Однако в своей области она на порядок-другой быстрее конкурентов. Также, благодаря специализированности, CH предоставляет богатейшие возможности прямо из коробки. Собственно, этот абзац - не более чем пересказ небольшой части документации
. Документация отличная, только не всегда поспевает за разработчиками :) Однако, чтобы добиться хорошей производительности, нужно предпринять определённые усилия.
Во-первых, хоть это и не указано в документации, CH нужна память. Для нормальной работы фонового слияния требуется примерно 9ГБ при условии среднего размера записи в 1К (формула приведена одним из разработчиков в гуглогруппе и выглядит как 600*<размер записи>*<гранулированность индекса>
). Нет, он и на 2ГБ памяти запустится и поначалу будет радовать производительностью, но только поначалу. Здесь и далее я пишу о движках семейства MergeTree - собственно, в общем случае кроме них ничего и не нужно.
Данные в CH заливаются действительно быстро, на шестиядерном процессоре я получил производительность более 100К записей размером более 800 байт в секунду каждая при вставке из Tab-separated файла. К сожалению, существует важное ограничение: вставка данных по одной строке приводит к деградации производительности до уровня тысяч в секунду, так что на стороне приложения необходим буфер. В CH есть движок Buffer, но он тоже не решает эту проблему.
Важное значение имеет так называемый "первичный ключ" (далее ПК). В CH этим словосочетанием обозначается список полей, из которых будет состоять индекс, а также, по необходимости, выражение для сэмплирования. Важно отметить, что ПК допускает повторяющиеся значения. В принципе, добавление в ПК новых столбцов если и влияет на производительность вставки, то очень слабо, основная проблема заключается в том, что на данный момент CH не поддерживает изменение типа столбца, входящего в ПК. Скорость же выборки может меняться в разы.
Значительного ускорения запросов можно добиться использованием PREWHERE вместо WHERE, если столбцы в условии есть в ПК.
CH не поддерживает изменение данных, а место на диске небесконечное, и тут на помощь приходит партиционирование. Работает оно автоматически, таблицы делятся на отдельные партиции по месяцам, исходя и информации обязательного ключа с датой в ПК, что даёт возможность при желании писать туда не настоящую дату и партиционировать данные произвольным образом. Партиции можно отключать и подключать на лету, отключенные можно сносить или копировать и подключать к другому серверу.
CH поддерживает JOIN и в принципе, довольно быстро их выполняет, но разработчики рекомендуют по возможности разворачивать данные в плоскую структуру. Вместо JOIN иногда можно использовать внешние словари.
Я сейчас пишу в CH слегка обработанные логи nginx и при среднесуточной загрузке около 1K запросов с помощью CH строю графики среднего времени выполнения, количества запросов и кодов возврата в разбивке по upstream и разным частям url. За месяц набирается около двух миллиардов записей и не наблюдается никакой деградации производительности. Естественно, постоянно делаю и более сложные запросы, котороые тоже радуют своей производительностью. Записываю данные сделанным на коленке syslog сервером, умеющим только принимать логи и отдавать их CH при накоплении определённого количества.