Как выбрать ключ шардинга для ClickHouse
Что проверяют
Понимаете ли вы, что ключ шардинга в ClickHouse решает не только равномерность дисков, но и то, какие запросы посчитаются локально на шарде, а какие погонят данные по сети. Следом обычно спрашивают, как поменять неудачный ключ на живом кластере.
Как отвечать
Начните с механики. Ключ задаётся аргументом движка Distributed(cluster, db, table, sharding_key): это выражение, по остатку от деления которого на сумму весов шардов (weight в описании кластера) выбирается шард для строки. Дальше критерии выбора:
- равномерность: колонка с высокой кардинальностью под хэшем, например
cityHash64(user_id).rand()даёт идеальный баланс, но размазывает данные одного пользователя по всем шардам; - локальность: если события пользователя лежат на одном шарде, сессии, воронки и
uniqпо пользователю считаются там же, без пересылки промежуточных состояний. Таблицы, которые соединяют черезJOINилиIN, шардируют одним ключом, иначе нуженGLOBAL INс рассылкой подзапроса на каждый шард; - пропуск шардов: при фильтре по ключу настройка
optimize_skip_unused_shardsотправит запрос только на нужные шарды; - перекос: крупный клиент целиком на одном шарде делает его горячим. Выручает составной ключ, но тогда запросы по этому клиенту снова идут на весь кластер.
Разведите понятия: ключ шардинга раскладывает строки по серверам, а ORDER BY и PARTITION BY в MergeTree устраивают данные внутри шарда.
Про смену ключа ответьте честно: автоматического решардинга нет. Создают новые таблицы с новым ключом и переливают данные через INSERT ... SELECT, либо пишут свежие данные по новому ключу, а старые доживают до TTL в прежней таблице.
Где спотыкаются
Шардируют по дате. Все сегодняшние вставки уходят на один шард, он захлёбывается, остальные простаивают.
Берут rand() ради баланса, а потом каждый запрос по пользователю опрашивает весь кластер и сливает состояния агрегатов на инициаторе.
Путают шардинг с партиционированием и рассказывают про удаление старых партиций вместо распределения по узлам.