Сжатие в ClickHouse
Одним из секретов производительности запросов ClickHouse является сжатие.
Меньше данных на диске означает меньше ввода-вывода и более быстрые запросы и вставки. Накладные расходы любого алгоритма сжатия в отношении CPU в большинстве случаев перекрываются сокращением ввода-вывода. Улучшение сжатия данных, следовательно, должно стать первой целью при работе над обеспечением быстрой работы запросов в ClickHouse.
Почему ClickHouse так хорошо сжимает данные, мы рекомендуем эту статью. В кратком изложении, как столбцовая база данных, значения будут записываться в порядковой последовательности. Если эти значения отсортированы, одинаковые значения будут находиться рядом друг с другом. Алгоритмы сжатия используют непрерывные паттерны данных. Кроме того, ClickHouse имеет кодеки и детализированные типы данных, которые позволяют пользователям дополнительно настраивать техники сжатия.
На сжатие в ClickHouse влияют три основных фактора:
- Ключ сортировки
- Типы данных
- Каккие кодеки используются
Все это настраивается через схему.
Выбор правильного типа данных для оптимизации сжатия
Возьмем набор данных Stack Overflow в качестве примера. Сравним статистику сжатия для следующих схем таблицы posts
:
posts
- не оптимизированная по типу схема без ключа сортировки.posts_v3
- оптимизированная по типу схема с соответствующим типом и размером бит для каждого столбца с ключом сортировки(PostTypeId, toDate(CreationDate), CommentCount)
.
Используя следующие запросы, мы можем измерить текущий сжатый и несжатый размер каждого столбца. Давайте рассмотрим размер начальной оптимизированной схемы posts
без ключа сортировки.
Примечание о компактных и широких частях
Если вы видите значения compressed_size
или uncompressed_size
, равные 0
, это может быть связано с тем, что тип частей compact
, а не wide
(см. описание для part_type
в system.parts
).
Формат части контролируется настройками min_bytes_for_wide_part
и min_rows_for_wide_part
, означая что если вставленные
данные приводят к образованию части, которая не превышает значения вышеупомянутых настроек, то часть будет компактной, а не широкой, и вы не увидите значения для compressed_size
или uncompressed_size
.
Чтобы продемонстрировать:
Мы показываем как сжатый, так и несжатый размер здесь. Оба важны. Сжатый размер соответствует тому, что нам нужно прочитать с диска — это то, что мы хотим минимизировать для производительности запросов (и затрат на хранение). Эти данные должны быть распакованы перед чтением. Размер этого несжатого размера будет зависеть от используемого типа данных в данном случае. Минимизация этого размера снизит накладные расходы памяти запросов и количество данных, которые должны быть обработаны запросом, улучшая использование кэшей и в конечном итоге время выполнения запросов.
Вышеупомянутый запрос опирается на таблицу
columns
в системной базе данных. Эта база данных управляется ClickHouse и является сокровищницей полезной информации, от метрик производительности запросов до фоновых журналов кластера. Мы рекомендуем "Системные таблицы и окно в внутренности ClickHouse" и сопутствующие статьи[1][2] для любопытных читателей.
Чтобы подвести итог общего размера таблицы, мы можем упростить вышеупомянутый запрос:
Повторяя этот запрос для posts_v3
, таблицы с оптимизированным типом и ключом сортировки, мы можем наблюдать значительное снижение несжатых и сжатых размеров.
Полная разбивка по столбцам показывает значительную экономию для столбцов Body
, Title
, Tags
и CreationDate
, достигнутую благодаря упорядочиванию данных перед сжатием и использованию соответствующих типов.
Выбор правильного кодека сжатия столбца
С кодеками сжатия столбцов мы можем изменить алгоритм (и его настройки), используемый для кодирования и сжатия каждого столбца.
Кодировки и сжатие работают немного по-разному, но с одной и той же целью: уменьшить размер наших данных. Кодировки применяют отображение к нашим данным, преобразуя значения на основе функции, используя свойства типа данных. Напротив, сжатие использует общий алгоритм для сжатия данных на уровне байтов.
Как правило, кодировки применяются сначала, а затем используется сжатие. Поскольку разные кодировки и алгоритмы сжатия эффективны при разных распределениях значений, мы должны понимать наши данные.
ClickHouse поддерживает большое количество кодеков и алгоритмов сжатия. Ниже приведены некоторые рекомендации в порядке важности:
Рекомендация | Обоснование |
---|---|
ZSTD — вперед! | Сжатие ZSTD предлагает лучшие коэффициенты сжатия. ZSTD(1) должен быть по умолчанию для большинства общих типов. Более высокие коэффициенты сжатия можно добиться, изменяя числовое значение. Мы редко видим достаточные преимущества при значениях выше 3 из-за увеличенных затрат на сжатие (медленнее вставка). |
Delta для последовательностей дат и целых чисел | Кодеки, основанные на Delta , хорошо работают, когда у вас есть монотонные последовательности или небольшие дельты между последовательными значениями. Более конкретно, кодек Delta хорошо работает при условии, что производные дают маленькие числа. Если нет, стоит попробовать DoubleDelta (это обычно добавляет немного, если первая производная от Delta уже очень маленькая). Последовательности, где монотонное увеличение равномерно, будут сжиматься еще лучше, например, поля DateTime. |
Delta улучшает ZSTD | ZSTD является эффективным кодеком для данных дельты — наоборот, кодирование дельты может улучшить сжатие ZSTD . При наличии ZSTD другие кодеки редко предлагают дальнейшие улучшения. |
LZ4 вместо ZSTD , если возможно | если вы получаете сопоставимое сжатие между LZ4 и ZSTD , отдайте предпочтение первому, так как он предлагает более быстрое разжатие и требует меньше CPU. Однако в большинстве случаев ZSTD будет значительно превосходить LZ4 . Некоторые из этих кодеков могут работать быстрее в сочетании с LZ4 , обеспечивая аналогичное сжатие по сравнению с ZSTD без кодека. Это будет специфично для данных и требует тестирования. |
T64 для разреженных или малых диапазонов | T64 может быть эффективным для разреженных данных или когда диапазон в блоке небольшой. Избегайте T64 для случайных чисел. |
Gorilla и T64 для неизвестных паттернов? | Если данные имеют неизвестный паттерн, возможно, стоит попробовать Gorilla и T64 . |
Gorilla для данных об измерениях | Gorilla может быть эффективным для данных с плавающей точкой, особенно для тех, которые представляют показания измерительных приборов, т.е. случайные всплески. |
Смотрите здесь для дальнейших опций.
Ниже мы указываем кодек Delta
для Id
, ViewCount
и AnswerCount
, предполагая, что они будут линейно коррелированы с ключом сортировки и, таким образом, должны извлечь выгоду от кодирования Delta.
Улучшения сжатия для этих столбцов показаны ниже:
Сжатие в ClickHouse Cloud
В ClickHouse Cloud мы по умолчанию используем алгоритм сжатия ZSTD
(со значением по умолчанию 1). Хотя скорости сжатия могут варьироваться для этого алгоритма в зависимости от уровня сжатия (выше = медленнее), он имеет преимущество постоянной скорости на разжатии (около 20% вариации) и также позволяет параллелизацию. Наши исторические тесты также показывают, что этот алгоритм часто достаточно эффективен и даже может превзойти LZ4
, комбинированный с кодеком. Он эффективен для большинства типов данных и распределений информации, и, следовательно, является разумным универсальным вариантом по умолчанию, по этой причине наше начальное сжатие уже отлично, даже без оптимизации.