Перейти к содержимому
Последнее обновление

Бакетирование данных

Партицию можно дополнительно разделить на несколько бакетов данных в соответствии с требованиями бизнеса. Каждый бакет хранится как физический фрагмент данных (Tablet). Продуманная стратегия бакетирования позволяет существенно сократить объём данных, сканируемых во время запроса, повысить производительность запросов и увеличить возможности параллельной обработки.

Этот документ организован по пути принятия решений при создании таблицы: сначала выбирается способ бакетирования, затем ключ бакетирования и наконец количество бакетов и последующий подход к обслуживанию.

Быстрый выбор​

При создании таблицы дизайн бакетирования можно выполнить в следующем порядке:

ШагРешениеКлючевые факторы
1Выбрать способ бакетированияНаличие столбцов, часто используемых для фильтрации, равномерность данных и модель таблицы
2Выбрать ключ бакетирования (только для Hash-бакетирования)Условия фильтрации запросов, кардинальность столбцов, характеристики параллелизма и пропускной способности запросов
3Определить количество бакетовРазмер данных в каждом Tablet, количество BE и дисков
4Спланировать стратегию обслуживания бакетовТенденция роста данных и использование динамического партиционирования

1. Выбор способа бакетирования​

Doris поддерживает два способа бакетирования: Hash-бакетирование и Random-бакетирование. Их основные различия представлены ниже:

Критерий сравненияHash-бакетированиеRandom-бакетирование
Способ распределения данныхРазделение по значению Hash ключа бакетированияСлучайное равномерное распределение
Требуется ли ключ бакетированияДаНет
Поддерживается ли отсечение бакетовДаНет
Поддерживаемые модели таблицDUPLICATE / UNIQUE / AGGREGATEТолько DUPLICATE
Риск перекоса данныхЗависит от выбора ключа бакетированияНиже
Сценарии примененияТочечные запросы с частой фильтрацией по определённому столбцуАнализ по произвольным измерениям и данные, склонные к перекосу

1. Hash-бакетирование​

При создании таблицы или добавлении новой партиции необходимо выбрать один или несколько столбцов в качестве ключа бакетирования и явно указать количество бакетов. В одной партиции система вычисляет Hash на основе ключа бакетирования и количества бакетов, а строки с одинаковым значением Hash назначаются в один бакет.

Например, на рисунке ниже партиция p250102 разделена на 3 бакета по столбцу region, а строки с одинаковым значением Hash помещены в один бакет.

hash-bucket

Рекомендуемые сценарии:

  • Если бизнес часто фильтрует данные по определённому полю, это поле можно использовать как ключ бакетирования и повысить эффективность запросов за счёт отсечения бакетов.
  • Данные в таблице распределены относительно равномерно и вероятность перекоса невелика.

Пример: создание таблицы с Hash-бакетированием. Подробный синтаксис см. в разделе CREATE TABLE.

В примерах ниже имена таблиц указаны с базой данных demo; если в кластере она отсутствует, сначала создайте её:

CREATE DATABASE IF NOT EXISTS demo;
CREATE TABLE demo.hash_bucket_tbl(
oid BIGINT,
dt DATE,
region VARCHAR(10),
amount INT
)
DUPLICATE KEY(oid)
PARTITION BY RANGE(dt) (
PARTITION p250101 VALUES LESS THAN("2025-01-01"),
PARTITION p250102 VALUES LESS THAN("2025-01-02")
)
DISTRIBUTED BY HASH(region) BUCKETS 8;

В этом примере DISTRIBUTED BY HASH(region) задаёт Hash-бакетирование и выбирает столбец region в качестве ключа бакетирования. BUCKETS 8 задаёт создание 8 бакетов.

2. Random-бакетирование​

Random-бакетирование случайным образом распределяет данные по бакетам внутри каждой партиции, не используя значение Hash какого-либо поля. Такой подход обеспечивает равномерное распределение данных и предотвращает перекос, вызванный неудачным выбором ключа бакетирования.

При загрузке данных каждая партия в рамках одного задания загрузки случайным образом записывается в Tablet, что обеспечивает равномерное распределение данных. Например, на рисунке ниже 8 партий данных случайным образом распределены по 3 бакетам в партиции p250102.

random-bucket

При использовании Random-бакетирования можно включить режим загрузки в один Tablet (установить load_to_single_tablet в true), чтобы данные одной партии записывались только в один фрагмент данных. Это позволяет:

  • Повысить параллелизм и пропускную способность крупномасштабных загрузок данных.
  • Сократить усиление записи, вызванное операциями загрузки данных и Compaction.
  • Повысить стабильность кластера.

Рекомендуемые сценарии:

  • Анализ по произвольным измерениям, когда в бизнесе нет фиксированных столбцов фильтрации или соединения.
  • Распределение данных часто запрашиваемых столбцов или комбинаций столбцов крайне неравномерно, поэтому необходимо избежать перекоса данных.

Неподходящие сценарии:

  • Точечные запросы: Random-бакетирование не выполняет отсечение по ключу бакетирования, поэтому сканируются все данные в совпавших партициях.
  • Таблицы UNIQUE и AGGREGATE: Random-бакетирование поддерживается только таблицами DUPLICATE.

Пример: создание таблицы с Random-бакетированием. Подробный синтаксис см. в разделе CREATE TABLE.

CREATE TABLE demo.random_bucket_tbl(
oid BIGINT,
dt DATE,
region VARCHAR(10),
amount INT
)
DUPLICATE KEY(oid)
PARTITION BY RANGE(dt) (
PARTITION p250101 VALUES LESS THAN("2025-01-01"),
PARTITION p250102 VALUES LESS THAN("2025-01-02")
)
DISTRIBUTED BY RANDOM BUCKETS 8;

В этом примере DISTRIBUTED BY RANDOM задаёт Random-бакетирование без выбора ключа бакетирования. BUCKETS 8 задаёт создание 8 бакетов.

2. Выбор ключа бакетирования​

Совет

Только Hash-бакетирование требует выбора ключа бакетирования. Для Random-бакетирования ключ не требуется.

Ключ бакетирования может состоять из одного или нескольких столбцов. Разные модели таблиц накладывают на ключ бакетирования следующие ограничения:

Модель таблицыДопустимые ключи бакетирования
DUPLICATEЛюбой столбец Key или Value
AGGREGATE / UNIQUEТолько столбцы Key (для обеспечения корректного агрегирования данных)

Принципы выбора​

При выборе ключа бакетирования с учётом характеристик бизнес-запросов можно руководствоваться следующими принципами:

ПринципОписаниеПреимущество
Использовать условия фильтрации запросовВыбирать в качестве ключа бакетирования столбцы, которые часто используются в фильтрах запросовПоддержка отсечения бакетов и сокращение объёма сканируемых данных
Использовать столбцы с высокой кардинальностьюВыбирать в качестве ключа бакетирования столбцы с большим количеством различных значенийРавномерное распределение данных и предотвращение перекоса
Сценарии высокопараллельных точечных запросовВыбирать один столбец или небольшое количество столбцов в качестве ключа бакетированияОдин запрос сканирует только один бакет, что уменьшает влияние операций ввода-вывода между запросами
Сценарии запросов с высокой пропускной способностьюВыбирать несколько столбцов в качестве ключа бакетированияДанные распределяются равномернее; если условия запроса не могут полностью сопоставиться с условиями равенства, повышается общая пропускная способность

3. Определение количества бакетов​

В Doris каждый Bucket хранится как физический файл (Tablet). Общее количество Tablet в таблице равно:

Total Tablets = partition_num × bucket_num
Внимание

После задания количества бакетов для Partition изменить его нельзя. При определении количества бакетов заранее учитывайте будущее расширение машин.

Начиная с версии 2.0 Doris поддерживает автоматическую установку количества бакетов в партиции на основе ресурсов машин и информации о кластере. В зависимости от требуемой точности оценки можно выбрать ручной или автоматический способ.

1. Ручная установка количества бакетов​

Количество бакетов задаётся с помощью предложения DISTRIBUTED:

-- Set hash bucket num to 8
DISTRIBUTED BY HASH(region) BUCKETS 8

-- Set random bucket num to 8
DISTRIBUTED BY RANDOM BUCKETS 8

Принципы принятия решения​

При определении количества бакетов соблюдайте следующие два принципа. Если они противоречат друг другу, приоритет имеет принцип размера:

  1. Принцип размера: рекомендуется, чтобы размер сжатых данных каждого Tablet (без индексов) составлял от 1 GB до 20 GB, а для таблиц Unique Key — не более 10 GB.

    • Слишком маленькие Tablet: агрегирование менее эффективно, а нагрузка на управление метаданными возрастает.
    • Слишком большие Tablet: усложняются миграция и восстановление реплик, а стоимость повторной попытки неудачного Schema Change увеличивается.
    • Фактический размер Tablet можно проверить с помощью SHOW TABLETS FROM your_table.
  2. Принцип количества: без учёта масштабирования рекомендуется, чтобы количество Tablet в таблице было немного больше общего количества дисков в кластере.

Учитывайте число строк в каждом MOW Tablet

Для таблиц MOW Unique Key следует учитывать не только размер сжатых данных, но и физическое количество строк в каждом Tablet. Base Compaction создаёт карту преобразования rowid для физических входных строк, участвующих в слиянии; основное хранилище сопоставления занимает примерно 8 байт на строку. В узких таблицах или таблицах с высокой степенью сжатия во время Compaction может закончиться память из-за большого количества строк, даже если размер Tablet соответствует приведённым выше рекомендациям. Оценки и рекомендации по устранению проблемы см. в разделе Накладные расходы памяти Compaction для больших MOW Tablet.

Кроме того, учитывайте следующее:

  • Количество бакетов должно быть целым кратным количеству BE, чтобы обеспечить равномерное распределение данных.
  • Количество бакетов в одной партиции обычно не должно превышать 128. Если требуется больше, сначала разделите таблицу на партиции.

Предположим, что в кластере 10 машин BE и на каждой машине по одному диску. Количество бакетов можно задать по следующей таблице:

Размер сжатых данных партицииРекомендуемое количество бакетов
< 1 GB1 бакет
1 - 10 GB10 бакетов
10 - 200 GB10 - 20 бакетов
> 200 GBСначала разделить таблицу на партиции
Совет

Размер данных таблицы можно проверить командой SHOW DATA. Полученный результат необходимо разделить на количество реплик, чтобы получить фактический размер данных таблицы.

2. Автоматическая установка количества бакетов​

Функция автоматического вывода количества бакетов прогнозирует будущий размер партиций на основе размеров партиций за недавний период и соответствующим образом определяет количество бакетов.

-- Set hash bucket auto
DISTRIBUTED BY HASH(region) BUCKETS AUTO
properties("estimate_partition_size" = "20G")

-- Set random bucket auto
DISTRIBUTED BY RANDOM BUCKETS AUTO
properties("estimate_partition_size" = "20G")

Свойство estimate_partition_size используется для корректировки первоначальной оценки размера партиции:

  • Параметр необязателен. Если он не указан, значение по умолчанию — 10GB.
  • Параметр влияет только на первоначальную оценку и не зависит от будущего размера партиции, который система позже выводит из исторических данных партиций.

Рассчитанное количество бакетов ограничивается конфигурациями FE autobucket_min_buckets и autobucket_max_buckets:

Конфигурация FEПо умолчаниюОписание
autobucket_min_buckets3Нижняя граница результата автоматического бакетирования. В серии 4.0 значение по умолчанию изменено с 1 на 3 начиная с версии 4.0.8, а в серии 4.1 — начиная с версии 4.1.4
autobucket_max_buckets128Верхняя граница результата автоматического бакетирования
Изменение поведения (4.0.8 / 4.1.4)

Значение по умолчанию autobucket_min_buckets изменено с 1 на 3 в версии 4.0.8 (серия 4.0) и версии 4.1.4 (серия 4.1). Ранее для небольшой партиции мог быть рассчитан один бакет, что приводило к недостаточному параллелизму и неравномерному распределению данных. После изменения автоматическое бакетирование никогда не создаёт меньше 3 бакетов.

Изменение влияет только на партиции, созданные после обновления; количество бакетов в существующих партициях не меняется. Чтобы сохранить прежнее поведение, явно установите autobucket_min_buckets обратно в 1.

4. Обслуживание бакетирования данных​

Совет

В настоящее время Doris поддерживает изменение количества бакетов только для вновь добавляемых партиций. Следующие операции не поддерживаются:

  1. Изменение типа бакетирования не поддерживается.
  2. Изменение ключа бакетирования не поддерживается.
  3. Изменение количества бакетов для уже созданных бакетов не поддерживается.

При создании таблицы количество бакетов для каждой партиции единообразно задаётся предложением DISTRIBUTED. Чтобы учитывать рост или уменьшение объёма данных, при динамическом добавлении партиций можно отдельно указать количество бакетов для новой партиции.

В следующих примерах показано, как изменить количество бакетов для вновь добавляемых партиций с помощью команды ALTER TABLE:

-- Modify hash bucket table
ALTER TABLE demo.hash_bucket_tbl
ADD PARTITION p250103 VALUES LESS THAN("2025-01-03")
DISTRIBUTED BY HASH(region) BUCKETS 16;

-- Modify random bucket table
ALTER TABLE demo.random_bucket_tbl
ADD PARTITION p250103 VALUES LESS THAN("2025-01-03")
DISTRIBUTED BY RANDOM BUCKETS 16;

-- Modify dynamic partition table
ALTER TABLE demo.dynamic_partition_tbl
SET ("dynamic_partition.buckets"="16");

После изменения количества бакетов результат можно проверить командой SHOW PARTITION.