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

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

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

Обзор

Асинхронные материализованные представления Selena поддерживают различные стратегии секционирования и функции, которые позволяют достичь следующих эффектов:

  • Инкрементальное построение

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

  • Инкрементальное обновление

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

  • Частичная материализация

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

  • Прозрачная перезапись запросов

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

Ограничения

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

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

  • OLAP таблицы Selena в default catalog
    • Поддерживаемая стратегия секционирования: Range partitioning, List Partitioning и Expression Partitioning
    • Поддерживаемые типы данных для Partitioning Key: INT, DATE, DATETIME и STRING
    • Поддерживаемые типы таблиц: Primary Key, Duplicate Key, Aggregate Key и Unique Key
    • Поддерживается как в shared-nothing кластере, так и в shared-data кластере
  • Таблицы в Hive Catalog, Hudi Catalog, Iceberg Catalog и Paimon Catalog
    • Поддерживаемый уровень секционирования: Первичный уровень
    • Поддерживаемые типы данных для Partitioning Key: INT, DATE, DATETIME и STRING
примечание
  • Вы не можете создать секционированное материализованное представление на основе несекционированной базовой (фактовой) таблицы.
  • Для OLAP таблиц Selena две соседние секции базовой таблицы должны иметь последовательные диапазоны.
  • Для многоуровневых секционированных базовых таблиц во внешних каталогах только путь секционирования первичного уровня может использоваться для создания секционированного материализованного представления. Например, для таблицы, секционированной в формате yyyyMMdd/hour, вы можете построить материализованное представление, секционированное только по yyyyMMdd.
  • Начиная с версии 1.5.0, Selena поддерживает создание секционированных материализованных представлений на таблицах Iceberg с Partition Transforms, и материализованные представления секционируются по столбцу после преобразования. Для получения дополнительной информации см. Ускорение запросов к озеру данных с материализованными представлениями - Выбор подходящей стратегии обновления.

Случаи использования

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

CREATE TABLE IF NOT EXISTS par_tbl1 (
datekey DATE, -- DATE type date column used as the Partitioning Key.
k1 STRING,
v1 INT,
v2 INT
)
ENGINE=olap
PARTITION BY RANGE (datekey) (
START ("2021-01-01") END ("2021-01-04") EVERY (INTERVAL 1 DAY)
)
DISTRIBUTED BY HASH(k1);

CREATE TABLE IF NOT EXISTS par_tbl2 (
datekey STRING, -- STRING type date column used as the Partitioning Key.
k1 STRING,
v1 INT,
v2 INT
)
ENGINE=olap
PARTITION BY RANGE (str2date(datekey, '%Y-%m-%d')) (
START ("2021-01-01") END ("2021-01-04") EVERY (INTERVAL 1 DAY)
)
DISTRIBUTED BY HASH(k1);

CREATE TABLE IF NOT EXISTS par_tbl3 (
datekey_new DATE, -- Equivalent column with par_tbl1.datekey.
k1 STRING,
v1 INT,
v2 INT
)
ENGINE=olap
PARTITION BY RANGE (datekey_new) (
START ("2021-01-01") END ("2021-01-04") EVERY (INTERVAL 1 DAY)
)
DISTRIBUTED BY HASH(k1);

Выравнивание секций один к одному

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

Partitioned Materialized View-1

  • Если Partitioning Key базовой таблицы имеет тип DATE или DATETIME, вы можете напрямую указать тот же Partitioning Key для материализованного представления.

    PARTITION BY <base_table_partitioning_column>

    Пример:

    CREATE MATERIALIZED VIEW par_mv1
    REFRESH ASYNC
    PARTITION BY datekey
    AS
    SELECT
    k1,
    sum(v1) AS SUM,
    datekey
    FROM par_tbl1
    GROUP BY datekey, k1;
  • Если Partitioning Key базовой таблицы имеет тип STRING, вы можете использовать функцию str2date для преобразования строки даты в тип DATE или DATETIME.

    PARTITION BY str2date(<base_table_partitioning_column>, <format>)

    Пример:

    CREATE MATERIALIZED VIEW par_mv2
    REFRESH ASYNC
    PARTITION BY str2date(datekey, '%Y-%m-%d')
    AS
    SELECT
    k1,
    sum(v1) AS SUM,
    datekey
    FROM par_tbl2
    GROUP BY datekey, k1;

Выравнивание секций с агрегацией временной гранулярности

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

Partitioned Materialized View-2

  • Если Partitioning Key базовой таблицы имеет тип DATE или DATETIME, вы можете напрямую использовать функцию date_trunc на Partitioning Key базовой таблицы.

    PARTITION BY date_trunc(<format>, <base_table_partitioning_column>)

    Пример:

    CREATE MATERIALIZED VIEW par_mv3
    REFRESH ASYNC
    PARTITION BY date_trunc('month', datekey)
    AS
    SELECT
    k1,
    sum(v1) AS SUM,
    datekey
    FROM par_tbl1
    GROUP BY datekey, k1;
  • Если Partitioning Key базовой таблицы имеет тип STRING, вы должны преобразовать Partitioning Key базовой таблицы в тип DATE или DATETIME в списке SELECT, установить для него псевдоним и использовать его в функции date_trunc для указания Partitioning Key материализованного представления.

    PARTITION BY 
    date_trunc(<format>, <mv_partitioning_column>)
    AS
    SELECT
    str2date(<base_table_partitioning_column>, <format>) AS <mv_partitioning_column>

    Пример:

    CREATE MATERIALIZED VIEW par_mv4
    REFRESH ASYNC
    PARTITION BY date_trunc('month', mv_datekey)
    AS
    SELECT
    datekey,
    k1,
    sum(v1) AS SUM,
    str2date(datekey, '%Y-%m-%d') AS mv_datekey
    FROM par_tbl2
    GROUP BY datekey, k1;

Выравнивание секций с настраиваемой временной гранулярностью

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

Вам нужно определить новую временную гранулярность (интервал), используя функцию time_slice на Partitioning Key базовой таблицы в списке SELECT, установить для него псевдоним и использовать его в функции date_trunc для указания Partitioning Key материализованного представления.

PARTITION BY
date_trunc(<format>, <mv_partitioning_column>)
AS
SELECT
-- You can use time_slice.
time_slice(<base_table_partitioning_column>, <interval>) AS <mv_partitioning_column>

Пример:

CREATE MATERIALIZED VIEW par_mv5
REFRESH ASYNC
PARTITION BY date_trunc('day', mv_datekey)
AS
SELECT
k1,
sum(v1) AS SUM,
time_slice(datekey, INTERVAL 5 MINUTE) AS mv_datekey
FROM par_tbl1
GROUP BY datekey, k1;

Выравнивание секций с несколькими базовыми таблицами

Partitioned Materialized View-3

Вы можете создать материализованное представление, секции которого выровнены с секциями нескольких базовых таблиц, при условии, что секции базовых таблиц могут быть выровнены друг с другом, то есть базовые таблицы используют один и тот же тип Partitioning Key. Вы можете использовать JOIN для соединения базовых таблиц и установить Partition Key как общий столбец. Альтернативно, вы можете соединить их с помощью UNION. Базовые таблицы с выровненными секциями называются эталонными таблицами. Изменения данных в любой из эталонных таблиц запустят задачу обновления соответствующих секций материализованного представления.

Эта функция поддерживается начиная с версии 1.5.0.

-- Connect tables with JOIN.
CREATE MATERIALIZED VIEW par_mv6
REFRESH ASYNC
PARTITION BY datekey
AS SELECT
par_tbl1.datekey,
par_tbl1.k1 AS t1k1,
par_tbl3.k1 AS t2k1,
sum(par_tbl1.v1) AS SUM1,
sum(par_tbl3.v1) AS SUM2
FROM par_tbl1 JOIN par_tbl3 ON par_tbl1.datekey = par_tbl3.datekey_new
GROUP BY par_tbl1.datekey, t1k1, t2k1;

-- Connect tables with UNION.
CREATE MATERIALIZED VIEW par_mv7
REFRESH ASYNC
PARTITION BY datekey
AS SELECT
par_tbl1.datekey,
par_tbl1.k1 AS t1k1,
sum(par_tbl1.v1) AS SUM1
FROM par_tbl1
GROUP BY
par_tbl1.datekey,
par_tbl1.k1
UNION ALL
SELECT
par_tbl3.datekey_new,
par_tbl3.k1 AS t2k1,
sum(par_tbl3.v1) AS SUM2
FROM par_tbl3
GROUP BY
par_tbl3.datekey_new,
par_tbl3.k1;

Достижение инкрементального обновления и прозрачной перезаписи

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

Для достижения этих целей вы должны учитывать следующие аспекты при создании материализованного представления:

  • Гранулярность обновления

    Вы можете использовать свойство partition_refresh_number для указания гранулярности каждой операции обновления. partition_refresh_number контролирует максимальное количество секций для обновления в задаче обновления при запуске обновления. Если количество секций для обновления превышает это значение, Selena разделит задачу обновления и выполнит ее пакетами. Секции обновляются в хронологическом порядке от наименее недавней секции к наиболее недавней секции (исключая секции, созданные динамически для будущего). Когда значение равно -1, задача обновления не будет разделена. Значение по умолчанию изменено с -1 на 1 начиная с версии 1.5.0, что означает, что Selena обновляет секции одну за другой.

  • Область материализации

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

  • Стратегия обновления

    • Материализованные представления с автоматическими стратегиями обновления (REFRESH ASYNC) автоматически обновляются каждый раз при изменении данных базовой таблицы.
    • Материализованные представления с регулярными стратегиями обновления (REFRESH ASYNC [START (<start_time>)] EVERY (INTERVAL <interval>)) обновляются регулярно с определенным интервалом.
    примечание

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

    • Материализованные представления с ручными стратегиями обновления (REFRESH MANUAL) могут быть обновлены только путем ручного выполнения оператора REFRESH MATERIALIZED VIEW. Вы можете указать временной диапазон секций для обновления, чтобы избежать обновления всего материализованного представления. Если вы указываете FORCE в операторе, Selena принудительно обновляет соответствующее материализованное представление или секции независимо от того, изменились ли данные в базовой таблице. Добавив WITH SYNC MODE к оператору, вы можете сделать синхронный вызов задачи обновления, и Selena возвращает результат задачи только когда задача успешно выполнена или завершилась неудачей.

Следующий пример создает секционированное материализованное представление par_mv8. Если Selena обнаруживает изменения данных в секции базовой таблицы, она обновляет соответствующую секцию в материализованном представлении. Задача обновления разделяется на пакеты, каждый из которых обновляет только одну секцию ("partition_refresh_number" = "1"). Сохраняются только две самые недавние секции ("partition_ttl_number" = "2"), остальные удаляются во время обновления.

CREATE MATERIALIZED VIEW par_mv8
REFRESH ASYNC
PARTITION BY datekey
PROPERTIES(
"partition_ttl_number" = "2",
"partition_refresh_number" = "1"
)
AS
SELECT
k1,
sum(v1) AS SUM,
datekey
FROM par_tbl1
GROUP BY datekey, k1;

Вы можете использовать оператор REFRESH MATERIALIZED VIEW для обновления этого материализованного представления. Следующий пример делает синхронный вызов для принудительного обновления некоторых секций par_mv8 в определенном временном диапазоне.

REFRESH MATERIALIZED VIEW par_mv8
PARTITION START ("2021-01-03") END ("2021-01-04")
FORCE WITH SYNC MODE;

Вывод:

+--------------------------------------+
| QUERY_ID |
+--------------------------------------+
| 1d1c24b8-bf4b-11ee-a3cf-00163e0e23c9 |
+--------------------------------------+
1 row in set (1.12 sec)

С функцией TTL только некоторые секции сохраняются в par_mv8. Таким образом, вы достигли материализации частичных данных, что важно в сценариях, где большинство запросов направлены на недавние данные. Функция TTL позволяет прозрачно ускорять запросы к новым данным (например, в течение недели или месяца) с помощью материализованного представления, значительно экономя затраты на хранение. Запросы, которые не попадают в этот временной диапазон, направляются к базовой таблице.

В следующем примере Запрос 1 будет ускорен материализованным представлением, поскольку он попадает в секцию, которая сохранена в par_mv8, в то время как Запрос 2 будет направлен к базовой таблице, поскольку он не попадает в временной диапазон, где секции сохранены.

-- Query 1
SELECT
k1,
sum(v1) AS SUM,
datekey
FROM par_tbl1
WHERE datekey='2021-01-04'
GROUP BY datekey, k1;

-- Query 2
SELECT
k1,
sum(v1) AS SUM,
datekey
FROM par_tbl1
WHERE datekey='2021-01-01'
GROUP BY datekey, k1;

Partitioned Materialized View-4