Равномерное распределение данных

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

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

  • Начиная с версии v3.1, вам не нужно указывать бакет‑ключ в предложении DISTRIBUTED BY при создании таблицы или добавлении партиции. StarRocks поддерживает случайное бакетирование (random bucketing), которое равномерно распределяет данные по всем бакетам.

  • Начиная с версии v2.5.7, можно не задавать вручную число бакетов при создании таблицы или добавлении партиции: StarRocks может автоматически определять число бакетов (BUCKETS). Однако если производительность вас не устраивает и вы знакомы с механизмом бакетирования, вы можете задать число бакетов вручную.

Введение

Общие методы распределения

Современные распределённые СУБД обычно используют базовые методы распределения: Round‑Robin, Range, List и Hash.

Data distribution method

  • Round‑Robin: циклическое распределение данных по узлам.

  • Range: распределение по диапазонам значений столбца партиционирования. На схеме диапазоны [1-3] и [4-6] сопоставлены разным узлам.

  • List: распределение по дискретным значениям столбцов партиционирования (например, пол, регион). Каждое значение сопоставляется узлу; несколько разных значений могут сопоставляться одному узлу.

  • Hash: распределение на основе хеш‑функции.

Для большей гибкости помимо одиночных методов можно комбинировать их — распространённые сочетания: Hash+Hash, Range+Hash, Hash+List.

Методы распределения в StarRocks

StarRocks поддерживает как раздельное, так и комбинированное использование методов распределения.

Помимо общих методов, StarRocks поддерживает Random‑распределение для упрощения настройки бакетирования.

StarRocks реализует двухуровневую схему «партиционирование + бакетирование».

  • Первый уровень — партиционирование: данные в таблице можно делить на партиции. Поддерживаются expression partitioning, range partitioning и list partitioning. Можно и без партиционирования (вся таблица — одна партиция).

  • Второй уровень — бакетирование: данные в партиции дополнительно распределяются по бакетам. Поддерживаются hash и random bucketing.

Метод распределения

Методы партиционирования и бакетирования

Описание

Random distribution

Random bucketing

Вся таблица считается одной партицией. Данные случайно распределяются по бакетам. Это метод по умолчанию.

Hash distribution

Hash bucketing

Вся таблица считается одной партицией. Данные распределяются по бакетам по хеш‑значениям бакет‑ключа.

Range+Random distribution

  1. Range partitioning
  2. Random bucketing

  1. Данные распределяются по партициям на основе диапазонов значений столбцов партиционирования.
  2. Внутри партиции данные случайно распределяются по бакетам.

Range+Hash distribution

  1. Range partitioning
  2. Hash bucketing

  1. Данные распределяются по партициям на основе диапазонов значений столбцов партиционирования.
  2. Внутри партиции данные распределяются по бакетам по хеш‑значениям бакет‑ключа.

List+Random distribution

  1. Expression или list partitioning
  2. Random bucketing

  1. Данные партиционируются на основе списков значений столбцов партиционирования.
  2. Внутри партиции данные случайно распределяются по бакетам.

List+Hash distribution

  1. Expression или list partitioning
  2. Hash bucketing

  1. Данные партиционируются на основе списков значений столбцов партиционирования.
  2. Внутри партиции данные распределяются по бакетам по хеш‑значениям бакет‑ключа.

  • Random distribution

    Если при создании таблицы не задать методы партиционирования и бакетирования, используется random distribution по умолчанию. В настоящий момент этот метод доступен только для таблиц Duplicate Key.

    CREATE TABLE site_access1 (
        event_day DATE,
        site_id INT DEFAULT '10', 
        pv BIGINT DEFAULT '0' ,
        city_code VARCHAR(100),
        user_name VARCHAR(32) DEFAULT ''
    )
    DUPLICATE KEY (event_day,site_id,pv);
    -- Because the partitioning and bucketing methods are not configured, random distribution is used by default.
    
  • Hash distribution

    CREATE TABLE site_access2 (
        event_day DATE,
        site_id INT DEFAULT '10',
        city_code SMALLINT,
        user_name VARCHAR(32) DEFAULT '',
        pv BIGINT SUM DEFAULT '0'
    )
    AGGREGATE KEY (event_day, site_id, city_code, user_name)
    -- Use hash bucketing as the bucketing method and must specify the bucketing key.
    DISTRIBUTED BY HASH(event_day,site_id); 
    
  • Range+Random distribution (в настоящий момент доступно только для Duplicate Key таблиц.)

    CREATE TABLE site_access3 (
        event_day DATE,
        site_id INT DEFAULT '10', 
        pv BIGINT DEFAULT '0' ,
        city_code VARCHAR(100),
        user_name VARCHAR(32) DEFAULT ''
    )
    DUPLICATE KEY(event_day,site_id,pv)
    -- Use expression partitioning as the partitioning method and configure a time function expression.
    -- You can also use range partitioning.
    PARTITION BY date_trunc('day', event_day);
    -- Because the bucketing method is not configured, random bucketing is used by default.
    
  • Range+Hash distribution

    CREATE TABLE site_access4 (
        event_day DATE,
        site_id INT DEFAULT '10',
        city_code VARCHAR(100),
        user_name VARCHAR(32) DEFAULT '',
        pv BIGINT SUM DEFAULT '0'
    )
    AGGREGATE KEY(event_day, site_id, city_code, user_name)
    -- Use expression partitioning as the partitioning method and configure a time function expression.
    -- You can also use range partitioning.
    PARTITION BY date_trunc('day', event_day)
    -- Use hash bucketing as the bucketing method and must specify the bucketing key.
    DISTRIBUTED BY HASH(event_day, site_id);
    
  • List+Random distribution (в настоящий момент доступно только для Duplicate Key таблиц.)

    CREATE TABLE t_recharge_detail1 (
        id bigint,
        user_id bigint,
        recharge_money decimal(32,2), 
        city varchar(20) not null,
        dt date not null
    )
    DUPLICATE KEY(id)
    -- Use expression partitioning as the partitioning method and specify the partitioning column.
    -- You can also use list partitioning.
    PARTITION BY (city);
    -- Because the bucketing method is not configured, random bucketing is used by default.
    
  • List+Hash distribution

    CREATE TABLE t_recharge_detail2 (
        id bigint,
        user_id bigint,
        recharge_money decimal(32,2), 
        city varchar(20) not null,
        dt date not null
    )
    DUPLICATE KEY(id)
    -- Use expression partitioning as the partitioning method and specify the partitioning column.
    -- You can also use list partitioning.
    PARTITION BY (city)
    -- Use hash bucketing as the bucketing method and must specify the bucketing key.
    DISTRIBUTED BY HASH(city,id); 
    

Партиционирование

Метод партиционирования делит таблицу на несколько партиций. Он используется прежде всего для разделения таблицы на различные единицы управления на основе партиционирующего ключа. Для каждой партиции можно задать стратегию хранения: число бакетов, стратегию hot/cold, тип носителя и число реплик. StarRocks позволяет использовать разные типы носителей в одном кластере: например, свежие данные хранить на SSD для ускорения запросов, а исторические — на SATA для снижения затрат.

Метод партиционирования

Сценарии

Способ создания партиций

Expression partitioning (рекомендуется)

Ранее называлось automatic partitioning. Более гибкий и удобный метод. Подходит для большинства сценариев, в том числе запросов и управления по непрерывным диапазонам дат или enum‑значениям.

Автоматически во время загрузки данных

Range partitioning (Legacy)

Простые упорядоченные данные, часто запрашиваемые и управляемые по непрерывным диапазонам дат/чисел. Например, исторические данные по месяцам, а свежие — по дням.

Вручную, динамически или пакетно

List partitioning (Legacy)

Запросы и управление по enum‑значениям, когда одной партиции нужно включать разные значения для каждого столбца партиционирования. Например, часто запрашиваются данные по странам и городам; можно выбрать city как столбец партиционирования и хранить в партиции данные по нескольким городам одной страны.

Вручную

Как выбирать столбцы и гранулярность партиционирования

  • Ключ партиционирования — один или несколько столбцов. Правильный выбор столбца может значительно сократить объём сканируемых данных. В большинстве систем используют партиционирование по времени для упрощения удаления просроченных данных и управления многоуровневым хранением hot/cold. В этом случае применяйте expression или range partitioning со столбцом времени. Если данные часто запрашиваются и управляются по ENUM‑значениям, используйте expression или list partitioning и выберите соответствующий столбец.

  • При выборе гранулярности учитывайте объём данных, шаблоны запросов и требуемую детальность управления.

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

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

    • Пример 3: если требуется ежедневное истечение данных, выбирайте дневную гранулярность.

Бакетирование

Метод бакетирования делит партицию на несколько бакетов. Данные в бакете называются tablet.

Поддерживаются random bucketing с версии v3.1 и hash bucketing.

  • Random bucketing: при создании таблицы или добавлении партиций бакет‑ключ не задаётся. Данные в партиции случайно распределяются по бакетам.

  • Hash bucketing: требуется указать бакет‑ключ. Данные в одной партиции делятся на бакеты по значениям ключа; строки с одинаковым значением попадают в один и тот же бакет.

Число бакетов: по умолчанию StarRocks автоматически определяет число бакетов (с v2.5.7). Его можно и задать вручную. Подробнее см. определение числа бакетов.

Создание и управление партициями

Создание партиций

Expression partitioning (рекомендуется)

Режим shared‑data поддерживает time function expression с v3.1.0 и column expression с v3.1.1.

Начиная с v3.0, StarRocks поддерживает expression partitioning (ранее — automatic partitioning), более гибкий и удобный метод. Он подходит для большинства случаев, например запросов и управления по непрерывным диапазонам дат или ENUM‑значениям.

Достаточно настроить выражение партиционирования при создании таблицы — StarRocks будет автоматически создавать партиции при загрузке данных. Нет нужды вручную заранее создавать множество партиций или настраивать свойства динамического партиционирования.

С v3.4 expression partitioning дополнительно оптимизирован: унифицирует стратегии партиционирования и поддерживает более сложные решения. Рекомендуется в большинстве случаев и в будущем заменит другие стратегии.

Пример 1: простое time function выражение с DATETIME‑столбцом.

CREATE TABLE site_access(
    event_day DATETIME NOT NULL,
    site_id INT DEFAULT '10',
    city_code VARCHAR(100),
    user_name VARCHAR(32) DEFAULT '',
    pv BIGINT DEFAULT '0'
)
DUPLICATE KEY(event_day, site_id, city_code, user_name)
PARTITION BY time_slice(event_day, INTERVAL 7 day)
DISTRIBUTED BY HASH(event_day, site_id)

Пример 2: column expression с несколькими столбцами.

CREATE TABLE t_recharge_detail1 (
    id bigint,
    user_id bigint,
    recharge_money decimal(32,2), 
    city varchar(20) not null,
    dt varchar(20) not null
)
DUPLICATE KEY(id)
PARTITION BY dt,city
DISTRIBUTED BY HASH(`id`);

Пример 3: сложное time function выражение с Unix‑timestamp столбцом.

CREATE TABLE orders (
    ts BIGINT NOT NULL,
    id BIGINT NOT NULL,
    city STRING NOT NULL
)
PARTITION BY from_unixtime(ts,'%Y%m%d');

Пример 4: смешанное выражение — time function + column expression.

CREATE TABLE orders (
    ts BIGINT NOT NULL,
    id BIGINT NOT NULL,
    city STRING NOT NULL
)
PARTITION BY from_unixtime(ts,'%Y%m%d'), city;

Range partitioning

Range partitioning подходит для простых непрерывных данных — временных рядов или числовых диапазонов.

Ручное создание партиций

Определите соответствие каждой партиции диапазону значений столбца партиционирования.

  • Столбец партиционирования типа date.

    CREATE TABLE site_access(
        event_day DATE,
        site_id INT,
        city_code VARCHAR(100),
        user_name VARCHAR(32),
        pv BIGINT SUM DEFAULT '0'
    )
    AGGREGATE KEY(event_day, site_id, city_code, user_name)
    PARTITION BY RANGE(event_day)(
        PARTITION p1 VALUES LESS THAN ("2020-01-31"),
        PARTITION p2 VALUES LESS THAN ("2020-02-29"),
        PARTITION p3 VALUES LESS THAN ("2020-03-31")
    )
    DISTRIBUTED BY HASH(site_id);
    
  • Столбец партиционирования типа integer.

    CREATE TABLE site_access(
        datekey INT,
        site_id INT,
        city_code SMALLINT,
        user_name VARCHAR(32),
        pv BIGINT SUM DEFAULT '0'
    )
    AGGREGATE KEY(datekey, site_id, city_code, user_name)
    PARTITION BY RANGE (datekey) (
        PARTITION p1 VALUES LESS THAN ("20200131"),
        PARTITION p2 VALUES LESS THAN ("20200229"),
        PARTITION p3 VALUES LESS THAN ("20200331")
    )
    DISTRIBUTED BY HASH(site_id);
    
  • Три специальных time‑функции как столбцы партиционирования (с v3.3.0).

    При явном задании соответствия партиций и диапазонов значений столбца можно использовать специальную time‑функцию, чтобы преобразовать значения timestamp или строк в даты и делить партиции по этим датам.

    -- A 10-digit timestamp accurate to the second, for example, 1703832553.
    CREATE TABLE site_access(
        event_time bigint,
        site_id INT,
        city_code SMALLINT,
        user_name VARCHAR(32),
        pv BIGINT SUM DEFAULT '0'
      )
    AGGREGATE KEY(event_time, site_id, city_code, user_name)
    PARTITION BY RANGE(from_unixtime(event_time)) (
        PARTITION p1 VALUES LESS THAN ("2021-01-01"),
        PARTITION p2 VALUES LESS THAN ("2021-01-02"),
        PARTITION p3 VALUES LESS THAN ("2021-01-03")
    )
    DISTRIBUTED BY HASH(site_id)
    ;
    
    -- A 13-digit timestamp accurate to the millisecond, for example, 1703832553219.
    CREATE TABLE site_access(
        event_time bigint,
        site_id INT,
        city_code SMALLINT,
        user_name VARCHAR(32),
        pv BIGINT SUM DEFAULT '0'
      )
    AGGREGATE KEY(event_time, site_id, city_code, user_name)
    PARTITION BY RANGE(from_unixtime_ms(event_time))(
        PARTITION p1 VALUES LESS THAN ("2021-01-01"),
        PARTITION p2 VALUES LESS THAN ("2021-01-02"),
        PARTITION p3 VALUES LESS THAN ("2021-01-03")
    )
    DISTRIBUTED BY HASH(site_id);
    
    CREATE TABLE site_access (
         event_time  varchar(100),
         site_id INT,
         city_code SMALLINT,
         user_name VARCHAR(32),
         pv BIGINT SUM DEFAULT '0'
    )
    AGGREGATE KEY(event_time, site_id, city_code, user_name)
    PARTITION BY RANGE(str2date(event_time, '%Y-%m-%d'))(
        PARTITION p1 VALUES LESS THAN ("2021-01-01"),
        PARTITION p2 VALUES LESS THAN ("2021-01-02"),
        PARTITION p3 VALUES LESS THAN ("2021-01-03")
    )
    DISTRIBUTED BY HASH(site_id);
    

Динамическое партиционирование

Свойства dynamic partitioning задаются при создании таблицы. StarRocks автоматически заблаговременно создаёт новые партиции и удаляет устаревшие, реализуя TTL‑управление для партиций.

В отличие от автоматического создания партиций в expression partitioning, динамическое партиционирование периодически создаёт новые партиции только по заданным свойствам. Если новые данные не попадают в созданные партиции, загрузка завершится ошибкой. Expression partitioning создаёт нужные партиции исходя из поступающих данных.

Пакетное создание нескольких партиций

Можно пакетно создавать партиции при и после создания таблицы. Укажите начало и конец диапазона в START() и END() и шаг в EVERY(). Диапазоны партиций лево‑замкнутые и право‑разомкнутые. Правила именования такие же, как у динамического партиционирования.

  • Столбец партиционирования типа date.

    При типе date в момент создания таблицы используйте START() и END() для указания даты начала и конца, а EVERY(INTERVAL xxx) — для шага. Поддерживаемая гранулярность интервала: HOUR (с v3.0), DAY, WEEK, MONTH, YEAR.

    В примере ниже партиции создаются с 2021‑01‑01 по 2021‑01‑04 с шагом 1 день:

    CREATE TABLE site_access (
        datekey DATE,
        site_id INT,
        city_code SMALLINT,
        user_name VARCHAR(32),
        pv BIGINT DEFAULT '0'
    )
    DUPLICATE KEY(datekey, site_id, city_code, user_name)
    PARTITION BY RANGE (datekey) (
        START ("2021-01-01") END ("2021-01-04") EVERY (INTERVAL 1 DAY)
    )
    DISTRIBUTED BY HASH(site_id);
    

    Эквивалентно следующему PARTITION BY:

    PARTITION BY RANGE (datekey) (
        PARTITION p20210101 VALUES [('2021-01-01'), ('2021-01-02')),
        PARTITION p20210102 VALUES [('2021-01-02'), ('2021-01-03')),
        PARTITION p20210103 VALUES [('2021-01-03'), ('2021-01-04'))
    )
    

    Можно создавать партии с разными интервалами, указав разные значения в EVERY для каждого блока (диапазоны не должны пересекаться). Например:

    CREATE TABLE site_access (
        datekey DATE,
        site_id INT,
        city_code SMALLINT,
        user_name VARCHAR(32),
        pv BIGINT DEFAULT '0'
    )
    DUPLICATE KEY(datekey, site_id, city_code, user_name)
    PARTITION BY RANGE (datekey) (
        START ("2019-01-01") END ("2021-01-01") EVERY (INTERVAL 1 YEAR),
        START ("2021-01-01") END ("2021-05-01") EVERY (INTERVAL 1 MONTH),
        START ("2021-05-01") END ("2021-05-04") EVERY (INTERVAL 1 DAY)
    )
    DISTRIBUTED BY HASH(site_id);
    

    Эквивалентно:

    PARTITION BY RANGE (datekey) (
        PARTITION p2019 VALUES [('2019-01-01'), ('2020-01-01')),
        PARTITION p2020 VALUES [('2020-01-01'), ('2021-01-01')),
        PARTITION p202101 VALUES [('2021-01-01'), ('2021-02-01')),
        PARTITION p202102 VALUES [('2021-02-01'), ('2021-03-01')),
        PARTITION p202103 VALUES [('2021-03-01'), ('2021-04-01')),
        PARTITION p202104 VALUES [('2021-04-01'), ('2021-05-01')),
        PARTITION p20210501 VALUES [('2021-05-01'), ('2021-05-02')),
        PARTITION p20210502 VALUES [('2021-05-02'), ('2021-05-03')),
        PARTITION p20210503 VALUES [('2021-05-03'), ('2021-05-04'))
    )
    
  • Столбец партиционирования типа integer.

    Для INT‑столбца в START и END задаётся диапазон, в EVERY — шаг. Пример:

    Значения в START() и END() должны быть в двойных кавычках, а в EVERY() — без кавычек.

В примере ниже диапазон начинается с 1 и заканчивается 5 с шагом 1:

```SQL
CREATE TABLE site_access (
    datekey INT,
    site_id INT,
    city_code SMALLINT,
    user_name VARCHAR(32),
    pv BIGINT DEFAULT '0'
)
DUPLICATE KEY(datekey, site_id, city_code, user_name)
PARTITION BY RANGE (datekey) (
    START ("1") END ("5") EVERY (1)
)
DISTRIBUTED BY HASH(site_id);
```

Эквивалентно:

```SQL
PARTITION BY RANGE (datekey) (
    PARTITION p1 VALUES [("1"), ("2")),
    PARTITION p2 VALUES [("2"), ("3")),
    PARTITION p3 VALUES [("3"), ("4")),
    PARTITION p4 VALUES [("4"), ("5"))
)
```

Можно создавать партии с разными шагами, указав разные значения EVERY для каждого блока (диапазоны не должны пересекаться):

```SQL
CREATE TABLE site_access (
    datekey INT,
    site_id INT,
    city_code SMALLINT,
    user_name VARCHAR(32),
    pv BIGINT DEFAULT '0'
)
DUPLICATE KEY(datekey, site_id, city_code, user_name)
PARTITION BY RANGE (datekey) (
    START ("1") END ("10") EVERY (1),
    START ("10") END ("100") EVERY (10)
)
DISTRIBUTED BY HASH(site_id);
```
  • Три специальных time‑функции как столбцы (с v3.3.0).

    Можно использовать time‑функции для преобразования timestamps или строк в дату и делить партиции по полученным датам.

    -- A 10-digit timestamp accurate to the second, for example, 1703832553.
    CREATE TABLE site_access(
        event_time bigint,
        site_id INT,
        city_code SMALLINT,
        user_name VARCHAR(32),
        pv BIGINT DEFAULT '0'
      )
    PARTITION BY RANGE(from_unixtime(event_time)) (
        START ("2021-01-01") END ("2021-01-10") EVERY (INTERVAL 1 DAY)
    )
    DISTRIBUTED BY HASH(site_id);
    -- A 13-digit timestamp accurate to the milliseconds, for example, 1703832553219.
    CREATE TABLE site_access(
        event_time bigint,
        site_id INT,
        city_code SMALLINT,
        user_name VARCHAR(32),
        pv BIGINT DEFAULT '0'
    )
    PARTITION BY RANGE(from_unixtime_ms(event_time))(
        START ("2021-01-01") END ("2021-01-10") EVERY (INTERVAL 1 DAY)
    )
    DISTRIBUTED BY HASH(site_id);
    
    CREATE TABLE site_access (
         event_time  varchar(100),
         site_id INT,
         city_code SMALLINT,
         user_name VARCHAR(32),
         pv BIGINT DEFAULT '0'
    )
    PARTITION BY RANGE(str2date(event_time, '%Y-%m-%d'))(
        START ("2021-01-01") END ("2021-01-10") EVERY (INTERVAL 1 DAY)
    )
    DISTRIBUTED BY HASH(site_id);
    

List partitioning (с v3.1)

List Partitioning подходит для ускорения запросов и эффективного управления данными по enum‑значениям. Особенно полезен, когда партиция должна включать данные с разными значениями в столбце партиционирования. Например, если часто запрашиваются данные по странам и городам, можно выбрать столбец city и хранить в одной партиции данные для разных городов одной страны.

StarRocks размещает данные в партициях на основе явного сопоставления со списками значений, заданными для каждой партиции.

Управление партициями

Добавление партиций

Для range и list partitioning можно вручную добавлять новые партиции для новых данных. Для expression partitioning партиции создаются автоматически при загрузке, вручную добавлять их не требуется.

Ниже добавляется новая партиция в таблицу site_access для хранения данных нового месяца:

ALTER TABLE site_access
ADD PARTITION p4 VALUES LESS THAN ("2020-04-30")
DISTRIBUTED BY HASH(site_id);

Удаление партиции

Следующий оператор удаляет партицию p1 из таблицы site_access.

Операция не удаляет данные немедленно. Они помещаются в корзину (Trash) на некоторый срок (по умолчанию сутки). Если партиция удалена ошибочно, используйте команду RECOVER для восстановления партиции и её данных.

ALTER TABLE site_access
DROP PARTITION p1;

Восстановление партиции

Восстановление партиции p1 и её данных в таблице site_access:

RECOVER PARTITION p1 FROM site_access;

Просмотр партиций

Возвращает сведения обо всех партициях таблицы site_access:

SHOW PARTITIONS FROM site_access;

Настройка бакетирования

Случайное бакетирование (с v3.1)

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

Однако, если объём данных велик и часто используются определённые столбцы в фильтрах, производительность random bucketing может быть недостаточной. В таких случаях рекомендуется hash bucketing. Если в запросах используются эти столбцы, сканируются только бакеты, по которым произошёл хит, что существенно ускоряет запросы.

Ограничения

  • Случайное бакетирование можно использовать только для Duplicate Key таблиц.

  • Таблицу со случайным бакетированием нельзя включать в Colocation Group.

  • Spark Load нельзя использовать для загрузки в такие таблицы.

В следующем примере CREATE TABLE не используется DISTRIBUTED BY xxx, поэтому применяется случайное бакетирование по умолчанию и число бакетов назначается автоматически:

CREATE TABLE site_access1(
    event_day DATE,
    site_id INT DEFAULT '10', 
    pv BIGINT DEFAULT '0' ,
    city_code VARCHAR(100),
    user_name VARCHAR(32) DEFAULT ''
)
DUPLICATE KEY(event_day,site_id,pv);

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

CREATE TABLE site_access2(
    event_day DATE,
    site_id INT DEFAULT '10', 
    pv BIGINT DEFAULT '0' ,
    city_code VARCHAR(100),
    user_name VARCHAR(32) DEFAULT ''
)
DUPLICATE KEY(event_day,site_id,pv)
DISTRIBUTED BY RANDOM BUCKETS 8; -- manually set the number of buckets to 8

Бакетирование на основе хэша

StarRocks делит данные в партиции на бакеты на основе бакет‑ключа и числа бакетов. При этом хеш‑функция вычисляет хеш‑значение по бакет‑ключу строки; соответствие хешей и бакетов определяет размещение строки.

Преимущества

  • Ускорение запросов: строки с одинаковыми значениями ключа лежат в одном бакете, что уменьшает объём сканирования.

  • Равномерное распределение: выбор столбцов с высокой кардинальностью (много уникальных значений) в качестве ключа помогает равномерно распределять данные.

Как выбирать бакет‑столбцы

Рекомендуется выбирать столбец, удовлетворяющий двум требованиям:

  • высокая кардинальность (например, ID)

  • часто используется в фильтрах

Если таких нет, выбирайте по сложности запросов:

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

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

Если с одним столбцом данные распределяются неравномерно, используйте несколько бакет‑столбцов (желательно не более трёх).

Особенности

  • При создании таблицы необходимо указать бакет‑столбцы.

  • Допустимые типы: INTEGER, DECIMAL, DATE/DATETIME, CHAR/VARCHAR/STRING.

  • С версии 3.2 бакет‑столбцы можно изменять через ALTER TABLE после создания.

Примеры

В примере ниже таблица site_access создаётся с site_id как бакет‑столбцом. Часто фильтрация выполняется по сайтам, поэтому такой выбор позволяет отсекать большинство нерелевантных бакетов.

CREATE TABLE site_access(
    event_day DATE,
    site_id INT DEFAULT '10',
    city_code VARCHAR(100),
    user_name VARCHAR(32) DEFAULT '',
    pv BIGINT SUM DEFAULT '0'
)
AGGREGATE KEY(event_day, site_id, city_code, user_name)
PARTITION BY RANGE(event_day)
(
    PARTITION p1 VALUES LESS THAN ("2020-01-31"),
    PARTITION p2 VALUES LESS THAN ("2020-02-29"),
    PARTITION p3 VALUES LESS THAN ("2020-03-31")
)
DISTRIBUTED BY HASH(site_id);

Предположим, у каждой партиции 10 бакетов. В запросе ниже 9 из 10 бакетов будут отсечены, и StarRocks просканирует лишь 1/10 данных:

select sum(pv)
from site_access
where site_id = 54321;

Если site_id распределён неравномерно и многие запросы запрашивают данные по нескольким сайтам, одного столбца может быть недостаточно и возникнет перекос. В таком случае используйте комбинированный ключ, например site_id и city_code:

CREATE TABLE site_access
(
    site_id INT DEFAULT '10',
    city_code SMALLINT,
    user_name VARCHAR(32) DEFAULT '',
    pv BIGINT SUM DEFAULT '0'
)
AGGREGATE KEY(site_id, city_code, user_name)
DISTRIBUTED BY HASH(site_id,city_code);

На практике выбирайте один‑два столбца в зависимости от характера нагрузки. Один столбец site_id выгоден для коротких запросов — меньше обмена данными между узлами и выше производительность кластера. Два столбца site_id и city_code предпочтительны для длинных запросов — лучше используется параллелизм распределённого кластера.

  • Короткие запросы сканируют небольшой объём и могут выполняться на одном узле.

  • Длинные запросы сканируют большие объёмы и выигрывают от параллельного сканирования на нескольких узлах.

Установка числа бакетов

Бакеты отражают фактическую организацию файлов данных в StarRocks.

При создании таблицы

  • Автоматически (рекомендуется)

    С v2.5.7 StarRocks может автоматически определять число бакетов для партиции исходя из ресурсов и объёма данных.

    Если объём «сырых» данных в партиции превышает 100 GB, рекомендуется настроить число бакетов вручную (см. Метод 2).

    Пример:

    CREATE TABLE site_access (
        site_id INT DEFAULT '10',
        city_code SMALLINT,
        user_name VARCHAR(32) DEFAULT '',
        event_day DATE,
        pv BIGINT SUM DEFAULT '0')
    AGGREGATE KEY(site_id, city_code, user_name,event_day)
    PARTITION BY date_trunc('day', event_day)
    DISTRIBUTED BY HASH(site_id,city_code); -- do not need to set the number of buckets
    

    Для таблиц с random bucketing, помимо автоопределения числа бакетов в партиции, начиная с v3.2.0 логика дополнительно оптимизирована: StarRocks может динамически увеличивать число бакетов в партиции во время загрузки данных исходя из ёмкости кластера и объёма загружаемых данных.

    • Чтобы включить динамическое увеличение числа бакетов по требованию, задайте свойство таблицы PROPERTIES("bucket_size"="xxx") — размер одного бакета. Для небольших объёмов установите 1 GB, иначе 4 GB.

    • При включённом динамическом увеличении числа бакетов и необходимости отката на версию 3.1 нужно сначала удалить такую таблицу, затем вручную выполнить чекпойнт метаданных с помощью ALTER SYSTEM CREATE IMAGE, и только после этого выполнять откат.

    Пример:

    CREATE TABLE details1 (
        event_day DATE,
        site_id INT DEFAULT '10', 
        pv BIGINT DEFAULT '0',
        city_code VARCHAR(100),
        user_name VARCHAR(32) DEFAULT '')
    DUPLICATE KEY (event_day,site_id,pv)
    PARTITION BY date_trunc('day', event_day)
    -- The number of buckets in a partition is automatically determined by **StarRocks** and the number dynamically increases on demand because the size of a bucket is set to 1 GB.
    PROPERTIES("bucket_size"="1073741824")
    ;
    
    CREATE TABLE details2 (
        event_day DATE,
        site_id INT DEFAULT '10',
        pv BIGINT DEFAULT '0' ,
        city_code VARCHAR(100),
        user_name VARCHAR(32) DEFAULT '')
    DUPLICATE KEY (event_day,site_id,pv)
    PARTITION BY date_trunc('day', event_day)
    -- The number of buckets in the table partition is automatically determined by **StarRocks**, and the number is fixed and does not dynamically increases on demand because the size of a bucket is not set.
    ;
    
  • Вручную

    С v2.4.0 StarRocks поддерживает параллельное сканирование одного tablet несколькими потоками, снижая зависимость производительности от количества tablet. Рекомендуется, чтобы один tablet содержал около 10 GB «сырых» данных. Если хотите задать число бакетов вручную, оцените объём данных в каждой партиции и решите, сколько tablet требуется.

    Чтобы включить параллельное сканирование tablet, установите глобальный параметр enable_tablet_internal_parallel = true (SET GLOBAL enable_tablet_internal_parallel = true;).

    CREATE TABLE site_access (
        site_id INT DEFAULT '10',
        city_code SMALLINT,
        user_name VARCHAR(32) DEFAULT '',
        event_day DATE,
        pv BIGINT SUM DEFAULT '0')
    AGGREGATE KEY(site_id, city_code, user_name,event_day)
    PARTITION BY date_trunc('day', event_day)
    DISTRIBUTED BY HASH(site_id,city_code) BUCKETS 30;
    -- Suppose the amount of raw data that you want to load into a partition is 300 GB.
    -- Because we recommend that each tablet contain 10 GB of raw data, the number of buckets can be set to 30.
    DISTRIBUTED BY HASH(site_id,city_code) BUCKETS 30;
    
    CREATE TABLE details (
        site_id INT DEFAULT '10', 
        city_code VARCHAR(100),
        user_name VARCHAR(32) DEFAULT '',
        event_day DATE,
        pv BIGINT DEFAULT '0'
    )
    DUPLICATE KEY (site_id,city_code)
    PARTITION BY date_trunc('day', event_day)
    DISTRIBUTED BY RANDOM BUCKETS 30
    ; 
    

После создания таблицы

  • Автоматически (рекомендуется)

    С v2.5.7 StarRocks может автоматически определять число бакетов в партиции исходя из ресурсов и объёма данных.

    Если объём «сырых» данных в партиции превышает 100 GB, рекомендуется вручную настроить число бакетов (Метод 2).

    -- Automatically set the number of buckets for all partitions.
    ALTER TABLE site_access DISTRIBUTED BY HASH(site_id,city_code);
    
    -- Automatically set the number of buckets for specific partitions.
    ALTER TABLE site_access PARTITIONS (p20230101, p20230102)
    DISTRIBUTED BY HASH(site_id,city_code);
    
    -- Automatically set the number of buckets for new partitions.
    ALTER TABLE site_access ADD PARTITION p20230106 VALUES [('2023-01-06'), ('2023-01-07'))
    DISTRIBUTED BY HASH(site_id,city_code);
    

    Для таблиц с random bucketing, помимо автоопределения числа бакетов в партиции, начиная с v3.2.0 StarRocks может динамически увеличивать число бакетов во время загрузки. Это упрощает создание партиций и повышает производительность пакетных загрузок.

    • Чтобы включить динамическое увеличение числа бакетов по требованию, задайте свойство таблицы PROPERTIES("bucket_size"="xxx") — размер одного бакета. Если объём небольшой — 1 GB, иначе — 4 GB.

    • Если включено динамическое увеличение и требуется откат на 3.1, сначала удалите такую таблицу, затем вручную выполните чекпойнт метаданных ALTER SYSTEM CREATE IMAGE и только затем откатывайтесь.

    -- The number of buckets for all partitions is automatically set by **StarRocks** and this number is fixed because the on-demand and dynamic increase of the number of buckets is disabled.
    ALTER TABLE details DISTRIBUTED BY RANDOM;
    -- The number of buckets for all partitions is automatically set by **StarRocks** and the on-demand and dynamic increase of the number of buckets is enabled.
    ALTER TABLE details SET("bucket_size"="1073741824");
    
    -- Automatically set the number of buckets for specific partitions.
    ALTER TABLE details PARTITIONS (p20230103, p20230104)
    DISTRIBUTED BY RANDOM;
    
    -- Automatically set the number of buckets for new partitions.
    ALTER TABLE details ADD PARTITION  p20230106 VALUES [('2023-01-06'), ('2023-01-07'))
    DISTRIBUTED BY RANDOM;
    
  • Вручную

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

    -- Manually set the number of buckets for all partitions 
    ALTER TABLE site_access
    DISTRIBUTED BY HASH(site_id,city_code) BUCKETS 30;
    -- Manually set the number of buckets for specific partitions.
    ALTER TABLE site_access
    partitions p20230104
    DISTRIBUTED BY HASH(site_id,city_code)  BUCKETS 30;
    -- Manually set the number of buckets for new partitions.
    ALTER TABLE site_access
    ADD PARTITION p20230106 VALUES [('2023-01-06'), ('2023-01-07'))
    DISTRIBUTED BY HASH(site_id,city_code) BUCKETS 30;
    
    -- Manually set the number of buckets for all partitions 
    ALTER TABLE details
    DISTRIBUTED BY RANDOM BUCKETS 30;
    -- Manually set the number of buckets for specific partitions.
    ALTER TABLE details
    partitions p20230104
    DISTRIBUTED BY RANDOM BUCKETS 30;
    -- Manually set the number of buckets for new partitions.
    ALTER TABLE details
    ADD PARTITION p20230106 VALUES [('2023-01-06'), ('2023-01-07'))
    DISTRIBUTED BY RANDOM BUCKETS 30;
    

    Задание значения по умолчанию для динамических партиций:

    ALTER TABLE details_dynamic
    SET ("dynamic_partition.buckets"="xxx");
    

Просмотр числа бакетов

После создания таблицы выполните SHOW PARTITIONS, чтобы увидеть число бакетов в каждой партиции. Для hash bucketing число бакетов фиксировано на партицию.

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

  • Для такого типа фактическая иерархия внутри партиции: partition > subpartition > bucket. Чтобы увеличить число бакетов, StarRocks фактически добавляет новый subpartition с заданным количеством бакетов. Поэтому SHOW PARTITIONS может вернуть несколько строк с одинаковым именем партиции — это информация о подпартициях в одной партиции.

Оптимизация распределения данных после создания таблицы (с 3.2)

Режим shared‑data в StarRocks пока не поддерживает эту возможность.

По мере изменения шаблонов запросов и объёмов данных изначальные настройки (метод бакетирования, число бакетов, sort key) могут перестать подходить и ухудшать производительность. В этом случае используйте ALTER TABLE для изменения метода бакетирования, числа бакетов и sort key. Например:

  • Увеличение числа бакетов при росте объёма данных в партициях

    Если объём данных стал значительно больше, необходимо изменить число бакетов, чтобы поддерживать размер tablet в диапазоне 1–10 GB.

  • Изменение бакет‑ключа для избежания перекоса данных

    Если текущий ключ вызывает перекос (например, задан только k1), укажите более подходящие столбцы или добавьте дополнительные. Например:

    ALTER TABLE t DISTRIBUTED BY HASH(k1, k2) BUCKETS 20;
    -- When the **StarRocks**'s version is 3.1 or later, and the table is Duplicate Key table, you can consider directly using the system's default bucketing settings, that is, random bucketing and the number of buckets automatically set by **StarRocks**.
    ALTER TABLE t DISTRIBUTED BY RANDOM;
    
  • Адаптация sort key при изменении шаблонов запросов

    Если в запросах стали использоваться дополнительные столбцы в условиях, имеет смысл скорректировать sort key. Например:

    ALTER TABLE t ORDER BY k2, k1;