Привет, Хабр!
В прошлых статьях мы разбирали основной движок ClickHouse — MergeTree, материализованые представления и словари. В этой статье разберем инструмент оптимизации — LowCardinality. Это не просто тип данных, а способ эффективной работы со строками.
1. LowCardinality
Прежде чем мы погрузимся в детали LowCardinality, давайте дадим определение понятию «кардинальность».
Кардинальность — это количество уникальных значений в столбце. Низкая кардинальность означает, что столбец содержит небольшое количество уникальных значений при большом общем количестве строк, а высокая, наоборот — это когда уникальных значений много или почти все значения уникальны.
Теперь поговорим о LowCardinality и о том, как это связано с кардинальностью.
LowCardinality(T) — это специальная «обёртка» над другим типом данных T (как правило, это String или FixedString), которая заставляет ClickHouse использовать словарное кодирование для колонки. Это значит, что ClickHouse создаст словарь уникальных значений и в основной таблице будет хранить лишь компактные числовые ссылки на него. Этот тип данных особенно эффективен для колонок, где количество уникальных значений значительно меньше общего числа строк. Такие колонки называют колонками с низкой кардинальностью.
1.1. Как это работает?
Представим, что у нас есть огромная таблица с миллионами записей о визитах на сайт. В этой таблице есть колонка browser, где хранится название браузера пользователя: «Chrome», «Яндекс.Браузер» и «Safari». Уникальных названий браузеров всего три, но сами строки повторяются миллионы раз.
Для простоты восприятия изобразим это следующим образом:

Постоянное дублирование строк неэффективно как для хранения, так и для скорости выполнения запросов. Гораздо эффективнее было бы присвоить каждому уникальному браузеру короткий числовой код (например, «Яндекс.Браузер» → 1, «Safari» → 2, «Chrome» → 3) и хранить в таблице именно эти числа. Здесь мы и можем использовать оптимизацию с помощью типа данных LowCardinality.
Изменим тип данных в нашей первоначальной колонке со String на LowCardinality(String):

ClickHouse «под капотом» сделал следующее (в упрощённом виде):
-
Создал словарь, где сохранил только уникальные значения браузеров, присвоив каждому уникальный числовой ключ.
-
В самой таблице вместо полного текстового значения для каждой строки сохранил лишь небольшой целочисленный индекс, указывающий на соответствующее значение в словаре.
Теперь давайте выполним следующий запрос:
SELECT browserFROM tableWHERE browser = 'Chrome'
Схематично выполнение запроса можно представить следующим образом:

-
ClickHouse видит в запросе значение «Chrome» и один раз смотрит в словарь, чтобы найти его числовой ключ, в данном случае — 3.
-
Теперь вся основная работа по фильтрации миллионов строк происходит с числами — это на порядки быстрее, чем искать по строкам.
-
Когда все строки с ключом 3 найдены, ClickHouse берёт эти ключи и, снова заглянув в словарь, превращает их обратно в строки «Chrome» для финального вывода. Этот шаг применяется лишь к небольшому набору итоговых строк, а не ко всей таблице.
1.2. Преимущества использования
-
Ускорение запросов: Запросы, использующие фильтрацию, группировку и сортировку по колонкам LowCardinality, выполняются значительно быстрее. ClickHouse оперирует с числами, что гораздо эффективнее, чем работа со строками.
-
Экономия места на диске: Хранение целочисленных индексов вместо повторяющихся строк или других значений может существенно сократить объём данных, занимаемый колонкой на диске.
2. Рекомендации по использованию
Главное правило — данных много, а уникальных значений мало.
Для чего подходит:
-
страны, города, регионы;
-
статусы: «new», «in_progress», «done», «error»;
-
типы устройств: «desktop», «mobile», «tablet»;
-
коды валют: «USD», «EUR», «RUB»;
-
названия браузеров, операционных систем;
-
HTTP-методы: «GET», «POST», «PUT»;
-
и т.д.
Тип данных LowCardinality наиболее эффективен для столбцов, содержащих до 10 000 уникальных значений, но может ухудшить производительность, когда их количество превышает 100 000. Стоит избегать использования LowCardinality для колонок с высокой кардинальностью (ID пользователей, ID заказов, полнотекстовые комментарии). В этих случаях размер словаря приблизится к размеру самих данных, а накладные расходы на его ведение сведут на нет всю пользу и даже замедлят работу. Также LowCardinality редко бывает полезен для числовых типов, так как они и так хранятся компактно.
Надеюсь, эта статья помогла вам понять, что такое LowCardinality и как он работает в ClickHouse.
P.S. Если вы хотите систематизировать знания и получить прочную теоретическую базу для дальнейшего освоения ClickHouse на практике, буду рад видеть вас на моем бесплатном курсе ClickHouse с нуля который охватывает все самое необходимое для уверенного старта в работе с технологией. Закрепить пройденную теорию можно на практическом продолжении курса ClickHouse с нуля: практика.
Удачи в изучении!
ссылка на оригинал статьи https://habr.com/ru/articles/1077906/