Bucketing
Краткое руководство по выбору между Hash Bucketing и Random Bucketing в Selena, включая их механизмы, компромиссы и рекомендуемые случаи использования.
Быстрое сравнение
| Аспект | Hash Bucketing | Random Bucketing |
|---|---|---|
| Пример | DISTRIBUTED BY HASH(id) BUCKETS 16 | DISTRIBUTED BY RANDOM |
| Объявление ключа | Требуется HASH(col1, …) | Отсутствует – строки назначаются по принципу round‑robin |
| Начальное количество bucket при пропуске | Автоматически выбирается при CREATE, затем фиксируется | Автоматически выбирается при CREATE; может расти при установке bucket_size |
| Разделение / сжатие tablet | Ручное ALTER … BUCKETS | Автоматическое разделение ⇢ только рост (≥ v1.5.2) |
| Устойчивость к перекосу | Зависит от кардинальности ключа | Высокая – равномерная по дизайну |
| Bucket pruning | ✅ (фильтры, соединения) | 🚫 (полное сканирование tablet) |
| Colocate joins | ✅ | 🚫 |
| Local aggregation / bucket-shuffle joins | ✅ | 🚫 |
| Поддерживаемые типы таблиц | Все | Только таблицы Duplicate Key |
Hash Bucketing
Как это работает
Строки назначаются tablet путем хеширования одного или нескольких столбцов. Количество tablet фиксируется после создания, если не изменяется вручную.
Требования
- Необходимо заранее выбрать стабильный, равномерно распределенный ключ с высокой кардинальностью. Кардинальность должна быть обычно в 1000 раз больше количества BE узлов, чтобы предотвратить перекос данных между hash bucket.
- Изначально выберите подходящий размер bucket, в идеале от 1 до 10 ГБ.
Преимущества
- Локальность запросов – селективные фильтры и соединения затрагивают меньше tablet.
- Colocate joins – таблицы фактов/измерений могут использовать общие hash ключи для высокоскоростных соединений.
- Предсказуемая структура – строки с одинаковым ключом всегда располагаются вместе.
- Local aggregation & bucket‑shuffle joins – идентичная hash структура между партициями обеспечивает локальную агрегацию и снижает затраты на перемешивание данных для больших соединений
Недостатки
- Уязвим к горячим tablet при перекосе распределения данных.
- Количество tablet статично; масштабирование требует DDL обслуживания.
- Недостаточное количество tablet может негативно повлиять на загрузку данных, сжатие данных и параллелизм выполнения запросов.
- Чрезмерное использование tablet увеличит объем метаданных.
Пример: Соединение измерений и фактов и Tablet Pruning
-- Таблица фактов, разделенная и hash‑bucketed по (customer_id)
CREATE TABLE sales (
sale_id bigint,
customer_id int,
sale_date date,
amount decimal(10,2)
) ENGINE = OLAP
DISTRIBUTED BY HASH(customer_id) BUCKETS 48
PARTITION BY date_trunc('DAY', sale_date)
PROPERTIES ("colocate_with" = "group1");
-- Таблица измерений hash‑bucketed по тому же ключу и количеству bucket, размещенная с таблицей sales
CREATE TABLE customers (
customer_id int,
region varchar(32),
status tinyint
) ENGINE = OLAP
DISTRIBUTED BY HASH(customer_id) BUCKETS 48
PROPERTIES ("colocate_with" = "group1");
-- Selena может выполнить tablet pruning
SELECT sum(amount)
FROM sales
WHERE customer_id = 123
-- Selena может выполнить local aggregation
SELECT customer_id, sum(amount) AS total_amount
FROM sales
GROUP BY customer_id
ORDER BY total_amount DESC LIMIT 100;
-- Selena может выполнить colocate join
SELECT c.region, sum(s.amount)
FROM sales s JOIN customers c USING (customer_id)
WHERE s.sale_date BETWEEN '2025-01-01' AND '2025-01-31'
GROUP BY c.region;
Что вы получаете от этого примера?
- Tablet pruning: предикат customer_id
WHERE customer_id = 123обеспечивает bucket pruning, по зволяя запросу обращаться только к одному tablet, что снижает задержку и циклы CPU, особенно для точечных поисков. - Local aggregation: когда ключ hash распределения является подмножеством ключа агрегации, Selena может обойти фазу shuffle агрегации, снижая общую стоимость.
- Colocated join: поскольку обе таблицы используют одинаковое количество bucket и ключ, каждый BE может соединить свою локальную пару tablet без сетевого перемешивания.
Когда использовать
- Стабильные схемы с хорошо известными ключами фильтрации/соединения распределения.
- Рабочие нагрузки хранилищ данных, которые выигрывают от bucket pruning.
- Вам нужна какая-то специфическая оптимизация, такая как colocate join/bucket shuffle join/local aggregation
- Вы используете таблицы Aggregate/Primary Key.
Random Bucketing
Как это работает
Строки назначаются по принципу round‑robin; ключ не указывается. С PROPERTIES ("bucket_size"="<bytes>"), Selena динамически разделяет tablet по мере роста партиций (v1.5.2+).
Преимущества
- Нулевой технический долг – никаких ключей, никаких вычислений bucket.
- Защита от перекоса записи – равномерная нагрузка на диски и BE.
- Эластичный рост – разделение tablet поддерживает быструю загрузку по мере роста данных или кластера.
Недостатки
- Отсутствие bucket pruning – каждый запрос сканирует все tablet в партиции.
- Отсутствие colocated joins – структура без ключей препятствует локальности.
- Ограничено таблицами Duplicate Key на сегодняшний день.
Когда использовать
- Таблицы логов/событий или мультитенантных SaaS, где ключи изменяются или перекашиваются.
- Конвейеры с интенсивной записью, где критична равномерная пропускная способность загрузки.
Операционные рекомендации
- Выберите размер bucket (например, 1 ГиБ) для random bucketing, чтобы включить автоматическое разделение.
- Для hash bucketing отслеживайте размер tablet; перераспределяйте до того, как tablet превысят 5–10 ГиБ