Распределённые таблицы и шардирование

Когда данные не влезают на один сервер, ClickHouse растёт вширь — на кластер.

Шардирование (sharding) — разбиение данных на части (шарды), хранящиеся на разных серверах, чтобы запрос выполнялся ими параллельно.

Два разных понятия: шарды и реплики

Их часто путают, но они решают разные задачи:

ПонятиеЗачем
Шардхранит часть данных; шарды вместе — весь объём. Дают масштаб и скорость.
Репликахранит копию шарда на другом сервере. Дают надёжность и отказоустойчивость.

Кластер обычно сочетает оба: данные разбиты на шарды, и у каждого шарда есть реплики.

             [ Кластер ]
  Шард 1                 Шард 2
  данные A..M            данные N..Z
  реплика 1a             реплика 2a
  реплика 1b             реплика 2b

Как кластер ускоряет запрос

Аналитический запрос отправляется всем шардам сразу. Каждый шард считает агрегат по своей части данных, затем частичные результаты собираются в один. Два шарда обработают вдвое больше данных за то же время — это горизонтальное масштабирование.

Движок Distributed

Физически данные лежат в локальных MergeTree-таблицах на каждом шарде. Поверх них создаётся «прокси»-таблица на движке Distributed, к которой обращаются запросы — она сама раскидывает их по шардам и собирает результат:

-- Локальная таблица есть на каждом шарде (events_local)
-- Distributed-таблица — единая точка входа для запросов
CREATE TABLE events_all AS events_local
ENGINE = Distributed(my_cluster, default, events_local, rand());

Последний аргумент — ключ шардирования: он определяет, на какой шард попадёт строка при вставке. Часто берут хеш от user_id, чтобы данные пользователя жили на одном шарде.

Как работает под капотом

При запросе к Distributed-таблице узел-инициатор рассылает подзапросы на шарды (на одну из реплик каждого), получает частичные агрегаты и доагрегирует их. Репликацию между копиями шарда обеспечивает движок ReplicatedMergeTree совместно с координатором (ZooKeeper / ClickHouse Keeper).

Выбор ключа шардирования

Хороший ключ распределяет данные равномерно и кладёт «связанные» строки вместе. Плохой ключ создаёт перекос: один шард забит, другие простаивают. Например, шардировать по стране — риск, что один популярный регион перегрузит свой шард.

Частые ошибки

  • Путать шард и реплику. Шарды — про объём/скорость, реплики — про надёжность; добавление реплик не увеличивает ёмкость.
  • Перекошенный ключ шардирования. Неравномерное распределение сводит на нет выигрыш кластера.
  • Запросы к локальным таблицам вместо Distributed. Тогда видна лишь часть данных одного шарда.

Итоги

  • Шарды делят данные ради масштаба и скорости; реплики копируют ради надёжности.
  • Движок Distributed — единая точка входа, раскидывающая запрос по шардам.
  • Ключ шардирования должен распределять данные равномерно.
  • Кластер выполняет аналитику параллельно на многих серверах.
Проверьте себя
1. Чем шард отличается от реплики?
AЭто синонимы
BШард хранит часть данных (масштаб/скорость), реплика — копию шарда (надёжность)
CШард — это копия, реплика — часть данных
DРеплика хранит индексы, шард — данные
2. Зачем нужен движок Distributed?
AЧтобы сжимать данные
BЧтобы быть единой точкой входа, раскидывать запрос по шардам и собирать результат
CЧтобы удалять старые данные
DЧтобы заменить ORDER BY