Распределённые таблицы в ClickHouse направляют запросы через несколько шардов и реплик, что позволяет обеспечивать горизонтальное масштабирование, балансировку нагрузки и отказоустойчивость в кластере.

1. Что такое распределённая таблица?

Распределённая таблица:

  • Не хранит данные непосредственно (служит маршрутизатором запросов).
  • Направляет чтение и запись в локальные таблицы на разных шардах.
  • Позволяет выполнять запросы параллельно на нескольких узлах.
  • Улучшает отказоустойчивость, перенаправляя запросы к доступным репликам.

Процесс работы распределённой таблицы

+-------------------------------+
|  Запрос клиента (SELECT, INSERT) |
+-------------------------------+
               |
               v
+--------------------------------+
| Распределённая таблица (Маршрутизатор запросов) |
+--------------------------------+
               |
    +-------------------+-------------------+
    |                   |                   |
    v                   v                   v
+-------------+   +-------------+   +-------------+
| Шард 1      |   | Шард 2      |   | Шард 3      |  (Данные)
| Реплика A   |   | Реплика A   |   | Реплика A   |
| Реплика B   |   | Реплика B   |   | Реплика B   |
+-------------+   +-------------+   +-------------+
 

✅ Запросы автоматически распределяются между узлами.

✅ Отказоустойчивость — если одна реплика выходит из строя, запросы перенаправляются на другую.

2. Как создать распределённую таблицу

Для использования распределённой таблицы необходимо:

  • Локальная таблица (MergeTree) на каждом шарде.
  • Распределённая таблица, которая маршрутизирует запросы.

Шаг 1: Создание локальной таблицы на каждом узле Создайте эту таблицу на каждом шарде:

CREATE TABLE events_local (
event_id UInt32,
event_time DateTime,
user_id UInt32 
) ENGINE = MergeTree() 
ORDER BY event_time;

✅ Каждый узел хранит часть данных.

Шаг 2: Создание распределённой таблицы Создайте распределённую таблицу на всех узлах для маршрутизации запросов.

CREATE TABLE events_distributed
ENGINE = Distributed(my_cluster, default, events_local, rand());

Разбор параметров:

  • my_cluster → Определён в конфигурации кластера ClickHouse (config.xml).
  • default → Название базы данных.
  • events_local → Локальная таблица.
  • rand() → Случайным образом выбирает шард для вставок. ✅ Запросы, отправленные в events_distributed, маршрутизируются на соответствующий шард.

3. Как распределённые таблицы обрабатывают запросы

✅ Чтение данных (SELECT):

SELECT COUNT(*) FROM events_distributed;

Запрос выполняется параллельно на всех шардах. ClickHouse объединяет результаты перед возвращением.

✅ Вставка данных (INSERT):

INSERT INTO events_distributed VALUES (1, now(), 1001);

Данные вставляются в один шард (основано на функции rand()).

🔹 Альтернатива: Распределение на основе хэша Вместо rand(), можно распределить данные на основе столбца:

CREATE TABLE events_distributed
ENGINE = Distributed(my_cluster, default, events_local, cityHash64(user_id));

✅ Обеспечивает, чтобы один и тот же пользователь всегда попадал на один и тот же шард.

4. Оптимизация запросов с распределёнными таблицами

✅ Выполнение запросов на конкретном шарде: Можно ограничить запросы конкретным шардом:

SELECT * FROM events_local ON CLUSTER my_cluster WHERE _shard_num = 1;

✅ Полезно для диагностики данных, специфичных для шарда.

✅ Включение prefer_localhost_replica (Быстрее запросы): Измените настройки кластера, чтобы предпочитать запросы к локальной реплике:

SET prefer_localhost_replica = 1;

✅ Уменьшает задержку при сетевых запросах между узлами.

5. Обработка дисбаланса данных в распределённых таблицах

🚨 Проблема: При добавлении нового узла старые данные остаются на существующих узлах. ✅ Решение: Перераспределение данных вручную.

Как перераспределить данные по шардом:

  1. Вставьте данные через распределённую таблицу:
INSERT INTO events_distributed SELECT * FROM events_distributed;
  1. Удалите старые данные с исходных шардов:
ALTER TABLE events_local DELETE WHERE 1;

✅ Обеспечивает равномерное распределение данных по всем узлам.

6. Итоги: Как работают распределённые таблицы

ОсобенностьОписание
Служит маршрутизатором запросовНе хранит данные, только перенаправляет запросы
Поддерживает шардированиеЗапросы выполняются параллельно на нескольких узлах
Автоматическая балансировка нагрузкиЧтение распределяется автоматически, запись может быть хешированной
Обрабатывает отказоустойчивостьЗапросы перенаправляются на доступные реплики в случае сбоя
Перераспределение данных вручнуюСтарые данные не перераспределяются автоматически при добавлении нового узла

🚀 Основной вывод: Распределённые таблицы обеспечивают масштабируемость, балансировку нагрузки и отказоустойчивость, что делает ClickHouse мощным выбором для анализа больших данных.