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

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

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

ПРИМЕЧАНИЕ

  • После того как распределение данных указано при создании таблицы и шаблоны запросов или характеристики данных в бизнес-сценарии изменяются, начиная с версии 1.5.0 Selena поддерживает изменение определенных свойств, связанных с распределением данных, после создания таблицы для соответствия требованиям производительности запросов в новейших бизнес-сценариях.
  • Начиная с версии 1.5.0, вам не нужно указывать ключ бакетирования в предложении DISTRIBUTED BY при создании таблицы или добавлении секции. Selena поддерживает случайное бакетирование, которое случайным образом распределяет данные по всем бакетам. Для получения дополнительной информации см. Случайное бакетирование.
  • Начиная с версии 1.5.0, вы можете выбрать не устанавливать количество бакетов вручную при создании таблицы или добавлении секции. Selena может автоматически установить количество бакетов (BUCKETS). Однако, если производительность не соответствует вашим ожиданиям после того, как Selena автоматически установила количество бакетов, и вы знакомы с механизмом бакетирования, вы все еще можете вручную установить количество бакетов.

Введение

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

Современные распределенные системы баз данных обычно используют следующие основные методы распределения: Round-Robin, Range, List и Hash.

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

  • Round-Robin: распределяет данные по разным узлам циклически.
  • Range: распределяет данные по разным узлам на основе диапазонов значений столбцов секционирования. Как показано на диаграмме, диапазоны [1-3] и [4-6] соответствуют разным узлам.
  • List: распределяет данные по разным узлам на основе дискретных значений столбцов секционирования, таких как пол и провинция. Каждое дискретное значение сопоставляется с узлом, и несколько разных значений могут быть сопоставлены с одним и тем же узлом.
  • Hash: распределяет данные по разным узлам на основе хеш-функции.

Для достижения более гибкого секционирования данных, помимо использования одного из вышеперечисленных методов распределения данных, вы также можете комбинировать эти методы на основе конкретных бизнес-требований. Распространенные комбинации включают Hash+Hash, Range+Hash и Hash+List.

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

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

ПРИМЕЧАНИЕ

В дополнение к общим методам распределения, Selena также поддерживает случайное распределение для упрощения конфигурации бакетирования.

Также Selena распределяет данные, реализуя двухуровневый метод секционирования + бакетирования.

  • Первый уровень - секционирование: Данные внутри таблицы могут быть секционированы. Поддерживаемые методы секционирования - это секционирование по выражениям, секционирование по диапазонам и секционирование по спискам. Или вы можете выбрать не использовать секционирование (вся таблица рассматривается как одна секция).
  • Второй уровень - бакетирование: Данные в секции должны быть дополнительно распределены в меньшие бакеты. Поддерживаемые методы бакетирования - это хеш и случайное бакетирование.
Метод распределенияМетод секционирования и бакетированияОписание
Случайное распределениеСлучайное бакетированиеВся таблица считается секцией. Данные в таблице случайным образом распределяются в разные бакеты. Это метод распределения данных по умолчанию.
Hash распределениеHash бакетированиеВся таблица считается секцией. Данные в таблице распределяются в соответствующие бакеты на основе хеш-значений ключа бакетирования данных с использованием хеш-функции.
Range+Случайное распределение
  1. Секционирование по выражениям или секционирование по диапазонам
  2. Случайное бакетирование
  1. Данные в таблице распределяются в соответствующие секции на основе диапазонов, в которые попадают значения столбцов секционирования.
  2. Данные в секции случайным образом распределяются по разным бакетам.
Range+Hash распределение
  1. Секционирование по выражениям или секционирование по диапазонам
  2. Hash бакетирование
  1. Данные в таблице распределяются в соответствующие секции на основе диапазонов, в которые попадают значения столбцов секционирования.
  2. Данные в секции распределяются в соответствующие бакеты на основе хеш-значений ключа бакетирования данных с использованием хеш-функции.
List+Случайное распределение
  1. Секционирование по выражениям или секционирование по спискам
  2. Случайное бакетирование
  1. Данные в таблице распределяются в соответствующие секции на основе диапазонов, в которые попадают значения столбцов секционирования.
  2. Данные в секции случайным образом распределяются по разным бакетам.
List+Hash распределение
  1. Секционирование по выражениям или секционирование по спискам
  2. Hash бакетирование
  1. Данные в таблице секционируются на основе списков значений, к которым принадлежат значения столбцов секционирования.
  2. Данные в секции распределяются в соответствующие бакеты на основе хеш-значений ключа бакетирования данных с использованием хеш-функции.
  • Случайное распределение

    Если вы не настраиваете методы секционирования и бакетирования при создании таблицы, по умолчанию используется случайное распределение. Этот метод распределения в настоящее время может использоваться только для создания таблицы 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);
    -- Поскольку методы секционирования и бакетирования не настроены, по умолчанию используется случайное распределение.
  • Hash распределение

    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)
    -- Используйте hash бакетирование как метод бакетирования и обязательно укажите ключ бакетирования.
    DISTRIBUTED BY HASH(event_day,site_id);
  • Range+Случайное распределение (Этот метод распределения в настоящее время может использоваться только для создания таблицы 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)
    -- Используйте секционирование по выражениям как метод секционирования и настройте выражение временной функции.
    -- Вы также можете использовать секционирование по диапазонам.
    PARTITION BY date_trunc('day', event_day);
    -- Поскольку метод бакетирования не настроен, по умолчанию используется случайное бакетирование.
  • Range+Hash распределение

    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)
    -- Используйте секционирование по выражениям как метод секционирования и настройте выражение временной функции.
    -- Вы также можете использовать секционирование по диапазонам.
    PARTITION BY date_trunc('day', event_day)
    -- Используйте hash бакетирование как метод бакетирования и обязательно укажите ключ бакетирования.
    DISTRIBUTED BY HASH(event_day, site_id);
  • List+Случайное распределение (Этот метод распределения в настоящее время может использоваться только для создания таблицы 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)
    -- Используйте секционирование по выражениям как метод секционирования и укажите столбец секционирования.
    -- Вы также можете использовать секционирование по спискам.
    PARTITION BY (city);
    -- Поскольку метод бакетирования не настроен, по умолчанию используется случайное бакетирование.
  • List+Hash распределение

    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)
    -- Используйте секционирование по выражениям как метод секционирования и укажите столбец секционирования.
    -- Вы также можете использовать секционирование по спискам.
    PARTITION BY (city)
    -- Используйте hash бакетирование как метод бакетирования и обязательно укажите ключ бакетирования.
    DISTRIBUTED BY HASH(city,id);

Секционирование

Метод секционирования разделяет таблицу на несколько секций. Секционирование в первую очередь используется для разделения таблицы на различные единицы управления (секции) на основе ключа секционирования. Вы можете установить стратегию хранения для каждой секции, включая количество бакетов, стратегию хранения горячих и холодных данных, тип носителя хранения и количество реплик. Selena позволяет использовать различные типы носителей хранения в кластере. Например, вы можете хранить последние данные на твердотельных накопителях (SSD) для улучшения производительности запросов, а исторические данные на жестких дисках SATA для снижения затрат на хранение.

Метод секционированияСценарииМетоды создания секций
Секционирование по выражениям (рекомендуется)Ранее известное как автоматическое секционирование. Этот метод секционирования более гибкий и простой в использовании. Он подходит для большинства сценариев, включая запросы и управление данными на основе непрерывных диапазонов дат или значений перечислений.Автоматически создается во время загрузки данных
Секционирование по диапазонамТипичный сценарий - хранение простых, упорядоченных данных, которые часто запрашиваются и управляются на основе непрерывных диапазонов дат/чисел. Например, в некоторых особых случаях исторические данные должны быть секционированы по месяцам, а недавние данные должны быть секционированы по дням.Создается вручную, динамически или пакетно
Секционирование по спискамТипичный сценарий - запрос и управление данными на основе значений перечислений, и секция должна включать данные с различными значениями для каждого столбца секционирования. Например, если вы часто запрашиваете и управляете данными на основе стран и городов, вы можете использовать этот метод и выбрать city в качестве столбца секционирования. Таким образом, секция может хранить данные для нескольких городов, принадлежащих одной стране.Создается вручную
Как выбрать столбцы секционирования и гранулярность
  • Ключ секционирования состоит из одного или нескольких столбцов секционирования. Выбор подходящего столбца секционирования может эффективно уменьшить объем данных, сканируемых во время запросов. В большинстве бизнес-систем обычно принимается секционирование на основе времени для решения определенных проблем, вызванных удалением просроченных данных, и для облегчения управления многоуровневым хранением горячих и холодных данных. В этом случае вы можете использовать секционирование по выражениям или секционирование по диапазонам и указать временной столбец в качестве столбца секционирования. Кроме того, если данные часто запрашиваются и управляются на основе значений ENUM, вы можете использовать секционирование по выражениям или секционирование по спискам и указать столбец, включающий эти значения, в качестве столбца секционирования.
  • При выборе гранулярности секционирования необходимо учитывать объем данных, шаблоны запросов и гранулярность управления данными.
    • Пример 1: Если месячный объем данных в таблице невелик, секционирование по месяцам может уменьшить количество метаданных по сравнению с секционированием по дням, тем самым уменьшая потребление ресурсов для управления метаданными и планирования.
    • Пример 2: Если месячный объем данных в таблице велик и запросы в основном запрашивают данные определенных дней, секционирование по дням может эффективно уменьшить объем данных, сканируемых во время запросов.
    • Пример 3: Если данные должны истекать ежедневно, рекомендуется секционирование по дням.

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

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

Поддерживаемые методы бакетирования - это случайное бакетирование (с версии v3.1) и hash бакетирование.

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

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

Количество бакетов: По умолчанию Selena автоматически устанавливает количество бакетов (с версии v2.5.7). Вы также можете вручную установить количество бакетов. Для получения дополнительной информации см. определение количества бакетов.

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

Создание секций

Секционирование по выражениям (рекомендуется)

УВЕДОМЛЕНИЕ

Начиная с версии 1.5.0, режим shared-data Selena поддерживает выражение временной функции и не поддерживает выражение столбца.

Начиная с версии 1.5.0, Selena поддерживает секционирование по выражениям](./expression_partitioning.md) (ранее известное как автоматическое секционирование), которое более гибкое и простое в использовании. Этот метод секционирования подходит для большинства сценариев, таких как запросы и управление данными на основе непрерывных диапазонов дат или значений ENUM.

Вам нужно только настроить выражение секции (выражение временной функции или выражение столбца) при создании таблицы, и Selena автоматически создаст секции во время загрузки данных. Вам больше не нужно вручную создавать множество секций заранее или настраивать свойства динамических секций.

Секционирование по диапазонам

Секционирование по диапазонам подходит для хранения простых непрерывных данных, таких как данные временных рядов или непрерывные числовые данные. Секционирование по диапазонам подходит для часто запрашиваемых данных на основе непрерывных диапазонов дат/чисел. Кроме того, оно может применяться в некоторых особых случаях, когда исторические данные должны быть секционированы по месяцам, а недавние данные должны быть секционированы по дням.

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

Что касается типа данных столбцов секционирования, до версии v3.3.0 секционирование по диапазонам поддерживало только столбцы секционирования типов date и integer. Начиная с версии 1.5.0, три конкретные временные функции могут использоваться в качестве столбцов секций. При явном определении отношения сопоставления между секциями и диапазонами значений столбцов секционирования вам нужно сначала использовать конкретную временную функцию для преобразования значений столбцов секционирования временных меток или строк в значения дат, а затем разделить секции на основе преобразованных значений дат.

к сведению
  • Если значение столбца секционирования является временной меткой, вам нужно использовать функцию from_unixtime или from_unixtime_ms для преобразования временной метки в значение даты при разделении секций. Когда используется функция from_unixtime, столбец секционирования поддерживает только типы INT и BIGINT. Когда используется функция from_unixtime_ms, столбец секционирования поддерживает только тип BIGINT.
  • Если значение столбца секционирования является строкой (тип STRING, VARCHAR или CHAR), вам нужно использовать функцию str2date для преобразования строки в значение даты при разделении секций.
Ручное создание секций

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

  • Столбец секционирования имеет тип 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);
  • Три конкретные временные функции могут использоваться в качестве столбцов секционирования (поддерживается с версии v3.3.0).

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

    -- 10-значная временная метка с точностью до секунды, например, 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)
    ;

    -- 13-значная временная метка с точностью до миллисекунды, например, 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);
Динамическое секционирование

Динамическое секционирование связанные свойства настраиваются при создании таблицы. Selena автоматически создает новые секции заранее и удаляет просроченные секции для обеспечения свежести данных, что реализует управление временем жизни (TTL) для секций.

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

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

Несколько секций могут быть созданы пакетно при и после создания таблицы. Вы можете указать время начала и окончания для всех секций, созданных пакетно, в START() и END() и значение приращения секции в EVERY(). Однако обратите внимание, что диапазон секций является левозакрытым и правооткрытым, который включает время начала, но не включает время окончания. Правило именования для секций такое же, как и для динамического секционирования.

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

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

    В следующем примере секции, созданные пакетно, начинаются с 2021-01-01 и заканчиваются на 2021-01-04, с приращением секции в один день:

    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 в операторе CREATE TABLE:

    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'))
    )
  • Столбец секционирования имеет тип integer.

    Когда тип данных столбца секционирования - INT, вы указываете диапазон секций в START и END и определяете значение приращения в EVERY. Пример:

    ПРИМЕЧАНИЕ

    Значения столбцов секционирования в START() и END() должны быть заключены в двойные кавычки, в то время как значение приращения в EVERY() не нужно заключать в двойные кавычки.

    В следующем примере диапазон всех секций начинается с 1 и заканчивается на 5, с приращением секции 1:

    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);

    Это эквивалентно использованию следующего предложения PARTITION BY в операторе CREATE TABLE:

    PARTITION BY RANGE (datekey) (
    PARTITION p1 VALUES [("1"), ("2")),
    PARTITION p2 VALUES [("2"), ("3")),
    PARTITION p3 VALUES [("3"), ("4")),
    PARTITION p4 VALUES [("4"), ("5"))
    )
  • Три конкретные временные функции могут использоваться в качестве столбцов секционирования (поддерживается с версии v3.3.0).

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

    -- 10-значная временная метка с точностью до секунды, например, 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);
    -- 13-значная временная метка с точностью до миллисекунд, например, 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);

Секционирование по спискам (с версии v3.1)

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

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

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

Добавление секций

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

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

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

Удаление секции

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

ПРИМЕЧАНИЕ

Эта операция не удаляет данные в секции немедленно. Данные сохраняются в корзине в течение определенного времени (один день по умолчанию). Если секция была удалена по ошибке, вы можете использовать команду 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)

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

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

Ограничения

  • Вы можете использовать случайное бакетирование только для создания таблицы Duplicate Key.
  • Вы не можете указать таблицу, бакетированную случайным образом, для принадлежности к Colocation Group.
  • Spark Load не может использоваться для загрузки данных в таблицы, бакетированные случайным образом.

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

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);

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

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; -- вручную установить количество бакетов равным 8

Hash бакетирование

Selena может использовать hash бакетирование для подразделения данных в секции на бакеты на основе ключа бакетирования и количества бакетов. В hash бакетировании хеш-функция принимает значение ключа бакетирования данных в качестве входных данных и вычисляет хеш-значение. Данные хранятся в соответствующем бакете на основе сопоставления между хеш-значениями и бакетами.

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

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

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

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

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

  • столбец с высокой кардинальностью, такой как ID
  • столбец, который часто используется в фильтре для запросов

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

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

Если данные секции не могут быть равномерно распределены по всем бакетам с использованием одного столбца бакетирования, вы можете выбрать несколько столбцов бакетирования. Обратите внимание, что рекомендуется использовать не более 3 столбцов.

Меры предосторожности

  • При создании таблицы вы должны указать столбцы бакетирования.
  • Типы данных столбцов бакетирования должны быть INTEGER, DECIMAL, DATE/DATETIME или CHAR/VARCHAR/STRING.
  • Начиная с версии 1.5.0, столбцы бакетирования могут быть изменены с помощью ALTER TABLE после создания таблицы.

Примеры

В следующем примере таблица site_access создается с использованием site_id в качестве столбца бакетирования. Кроме того, когда данные в таблице 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);

Предположим, что каждая секция таблицы site_access имеет 10 бакетов. В следующем запросе 9 из 10 бакетов исключаются, поэтому Selena нужно сканировать только 1/10 данных в таблице site_access:

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 выгодно для длинных запросов, поскольку оно может использовать общую параллельность распределенного кластера для значительного улучшения производительности.

ПРИМЕЧАНИЕ

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

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

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

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

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

    Начиная с версии 1.5.0, Selena поддерживает автоматическую установку количества бакетов на основе ресурсов машины и объема данных для секции.

    подсказка

    Если размер исходных данных секции превышает 100 ГБ, мы рекомендуем вручную настроить количество бакетов, используя Метод 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); -- не нужно устанавливать количество бакетов
  • Ручная установка количества бакетов

    Начиная с версии 1.5.0, Selena поддерживает использование нескольких потоков для параллельного сканирования tablet во время запроса, тем самым уменьшая зависимость производительности сканирования от количества tablet. Мы рекомендуем, чтобы каждый tablet содержал около 10 ГБ исходных данных. Если вы намереваетесь вручную установить количество бакетов, вы можете оценить объем данных в каждой секции таблицы, а затем решить количество 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;
    -- Предположим, что объем исходных данных, которые вы хотите загрузить в секцию, составляет 300 ГБ.
    -- Поскольку мы рекомендуем, чтобы каждый tablet содержал 10 ГБ исходных данных, количество бакетов может быть установлено равным 30.
    DISTRIBUTED BY HASH(site_id,city_code) BUCKETS 30;

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

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

    Начиная с версии 1.5.0, Selena поддерживает автоматическую установку количества бакетов на основе ресурсов машины и объема данных для секции.

    подсказка

    Если размер исходных данных секции превышает 100 ГБ, мы рекомендуем вручную настроить количество бакетов, используя Метод 2.

    -- Автоматически установить количество бакетов для всех секций.
    ALTER TABLE site_access DISTRIBUTED BY HASH(site_id,city_code);

    -- Автоматически установить количество бакетов для конкретных секций.
    ALTER TABLE site_access PARTITIONS (p20230101, p20230102)
    DISTRIBUTED BY HASH(site_id,city_code);

    -- Автоматически установить количество бакетов для новых секций.
    ALTER TABLE site_access ADD PARTITION p20230106 VALUES [('2023-01-06'), ('2023-01-07'))
    DISTRIBUTED BY HASH(site_id,city_code);
  • Ручная установка количества бакетов

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

    -- Вручную установить количество бакетов для всех секций 
    ALTER TABLE site_access
    DISTRIBUTED BY HASH(site_id,city_code) BUCKETS 30;
    -- Вручную установить количество бакетов для конкретных секций.
    ALTER TABLE site_access
    partitions p20230104
    DISTRIBUTED BY HASH(site_id,city_code) BUCKETS 30;
    -- Вручную установить количество бакетов для новых секций.
    ALTER TABLE site_access
    ADD PARTITION p20230106 VALUES [('2023-01-06'), ('2023-01-07'))
    DISTRIBUTED BY HASH(site_id,city_code) BUCKETS 30;

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

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

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

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

УВЕДОМЛЕНИЕ

Режим shared-data Selena в настоящее время не поддерживает эту функцию.

По мере развития шаблонов запросов и объема данных в бизнес-сценариях конфигурации, указанные при создании таблицы, такие как метод бакетирования, количество бакетов и ключ сортировки, могут больше не подходить для нового бизнес-сценария и даже могут привести к снижению производительности запросов. В этот момент вы можете использовать ALTER TABLE для изменения метода бакетирования, количества бакетов и ключа сортировки для оптимизации распределения данных. Например:

  • Увеличение количества бакетов при значительном увеличении объема данных внутри секций

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

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

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

    ALTER TABLE t DISTRIBUTED BY HASH(k1, k2) BUCKETS 20;
    -- Когда версия Selena 3.1 или более поздняя, и таблица является таблицей Duplicate Key, вы можете рассмотреть возможность прямого использования настроек бакетирования системы по умолчанию, то есть случайного бакетирования и количества бакетов, автоматически установленного Selena.
    ALTER TABLE t DISTRIBUTED BY RANDOM;
  • Адаптация ключа сортировки из-за изменений в шаблонах запросов

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

    ALTER TABLE t ORDER BY k2, k1;

Для получения дополнительной информации см. ALTER TABLE.