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

Перезапись запросов с материализованными представлениями

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

Обзор

Асинхронное материализованное представление Selena использует широко распространенный алгоритм прозрачной перезаписи запросов, основанный на форме SPJG (select-project-join-group-by). Без необходимости изменения оператора запроса Selena может автоматически переписывать запросы к базовым таблицам в запросы к соответствующему материализованному представлению, которое содержит предварительно вычисленные результаты. В результате материализованные представления помогают существенно сократить вычислительные затраты и значительно ускорить выполнение запросов.

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

  • Предварительная агрегация метрик

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

  • Соединения широких таблиц

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

  • Ускорение запросов в озере данных

    Создание материализованного представления на основе external catalog может легко ускорить запросы к данным в вашем озере данных.

    ПРИМЕЧАНИЕ

    Асинхронные материализованные представления, созданные на базовых таблицах в JDBC catalog, не поддерживают перезапись запросов.

Возможности

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

  • Строгая согласованность данных: Если базовые таблицы являются нативными таблицами, Selena гарантирует, что результаты, полученные через перезапись запроса на основе материализованного представления, согласованы с результатами, возвращаемыми при прямом запросе к базовым таблицам.
  • Перезапись с устареванием: Selena поддерживает перезапись с устареванием, позволяя допускать определенный уровень истечения данных для работы со сценариями с частыми изменениями данных.
  • Многотабличные соединения: Асинхронное материализованное представление Selena поддерживает различные типы соединений, включая некоторые сложные сценарии соединений, такие как View Delta Joins и Derivable Joins, позволяя ускорить запросы в сценариях с большими широкими таблицами.
  • Перезапись агрегации: Selena может переписывать запросы с агрегациями для улучшения производительности отчетов.
  • Вложенное материализованное представление: Selena поддерживает перезапись сложных запросов на основе вложенных материализованных представлений, расширяя область применения запросов, которые могут быть переписаны.
  • Union перезапись: Вы можете объединить функцию Union перезаписи с TTL (Time-to-Live) разделов материализованного представления для достижения разделения горячих и холодных данных, что позволяет запрашивать горячие данные из материализованных представлений, а исторические данные из базовой таблицы.
  • Материализованные представления на представлениях: Вы можете ускорить запросы в сценариях с моделированием данных на основе представлений.
  • Материализованные представления на external catalogs: Вы можете ускорить запросы в озерах данных.
  • Перезапись сложных выражений: Может обрабатывать сложные выражения, включая вызовы функций и арифметические операции, удовлетворяя продвинутые аналитические и вычислительные требования.

Эти возможности будут подробно рассмотрены в следующих разделах.

Перезапись Join

Selena поддерживает перезапись запросов с различными типами соединений, включая Inner Join, Cross Join, Left Outer Join, Full Outer Join, Right Outer Join, Semi Join и Anti Join.

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

CREATE TABLE customer (
c_custkey INT(11) NOT NULL,
c_name VARCHAR(26) NOT NULL,
c_address VARCHAR(41) NOT NULL,
c_city VARCHAR(11) NOT NULL,
c_nation VARCHAR(16) NOT NULL,
c_region VARCHAR(13) NOT NULL,
c_phone VARCHAR(16) NOT NULL,
c_mktsegment VARCHAR(11) NOT NULL
) ENGINE=OLAP
DUPLICATE KEY(c_custkey)
DISTRIBUTED BY HASH(c_custkey) BUCKETS 12;

CREATE TABLE lineorder (
lo_orderkey INT(11) NOT NULL,
lo_linenumber INT(11) NOT NULL,
lo_custkey INT(11) NOT NULL,
lo_partkey INT(11) NOT NULL,
lo_suppkey INT(11) NOT NULL,
lo_orderdate INT(11) NOT NULL,
lo_orderpriority VARCHAR(16) NOT NULL,
lo_shippriority INT(11) NOT NULL,
lo_quantity INT(11) NOT NULL,
lo_extendedprice INT(11) NOT NULL,
lo_ordtotalprice INT(11) NOT NULL,
lo_discount INT(11) NOT NULL,
lo_revenue INT(11) NOT NULL,
lo_supplycost INT(11) NOT NULL,
lo_tax INT(11) NOT NULL,
lo_commitdate INT(11) NOT NULL,
lo_shipmode VARCHAR(11) NOT NULL
) ENGINE=OLAP
DUPLICATE KEY(lo_orderkey)
DISTRIBUTED BY HASH(lo_orderkey) BUCKETS 48;

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

CREATE MATERIALIZED VIEW join_mv1
DISTRIBUTED BY HASH(lo_orderkey)
AS
SELECT lo_orderkey, lo_linenumber, lo_revenue, lo_partkey, c_name, c_address
FROM lineorder INNER JOIN customer
ON lo_custkey = c_custkey;

Такое материализованное представление может переписать следующий запрос:

SELECT lo_orderkey, lo_linenumber, lo_revenue, c_name, c_address
FROM lineorder INNER JOIN customer
ON lo_custkey = c_custkey;

Rewrite-1

Selena поддерживает перезапись запросов с соединениями со сложными выражениями, такими как арифметические операции, строковые функции, функции даты, выражения CASE WHEN и предикаты OR. Например, приведенное выше материализованное представление может переписать следующий запрос:

SELECT 
lo_orderkey,
lo_linenumber,
(2 * lo_revenue + 1) * lo_linenumber,
upper(c_name),
substr(c_address, 3)
FROM lineorder INNER JOIN customer
ON lo_custkey = c_custkey;

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

Перезапись Query Delta Join

Query Delta Join относится к сценарию, в котором таблицы, соединенные в запросе, являются надмножеством таблиц, соединенных в материализованном представлении. Например, рассмотрим следующий запрос, который включает соединения трех таблиц: lineorder, customer и part. Если материализованное представление join_mv1 содержит только соединение lineorder и customer, Selena может переписать запрос, используя join_mv1.

Пример:

SELECT lo_orderkey, lo_linenumber, lo_revenue, c_name, c_address, p_name
FROM
lineorder INNER JOIN customer ON lo_custkey = c_custkey
INNER JOIN part ON lo_partkey = p_partkey;

Его исходный план запроса и план после перезаписи следующие:

Rewrite-2

Перезапись View Delta Join

View Delta Join относится к сценарию, в котором таблицы, соединенные в запросе, являются подмножеством таблиц, соединенных в материализованном представлении. Эта функция обычно используется в сценариях с большими широкими таблицами. Например, в контексте Star Schema Benchmark (SSB) вы можете создать материализованное представление, которое соединяет все таблицы для улучшения производительности запросов. При тестировании было обнаружено, что производительность запросов для многотабличных соединений может достичь того же уровня производительности, что и при запросе к соответствующей большой широкой таблице после прозрачной перезаписи запросов через материализованное представление.

Для выполнения перезаписи View Delta Join материализованное представление должно содержать соединение сохранения мощности 1:1, которое не существует в запросе. Вот девять типов соединений, которые считаются соединениями сохранения мощности, и удовлетворение любому из них позволяет выполнить перезапись View Delta Join:

Rewrite-3

Возьмем тесты SSB в качестве примера, создадим следующие базовые таблицы:

CREATE TABLE customer (
c_custkey INT(11) NOT NULL,
c_name VARCHAR(26) NOT NULL,
c_address VARCHAR(41) NOT NULL,
c_city VARCHAR(11) NOT NULL,
c_nation VARCHAR(16) NOT NULL,
c_region VARCHAR(13) NOT NULL,
c_phone VARCHAR(16) NOT NULL,
c_mktsegment VARCHAR(11) NOT NULL
) ENGINE=OLAP
DUPLICATE KEY(c_custkey)
DISTRIBUTED BY HASH(c_custkey) BUCKETS 12
PROPERTIES (
"unique_constraints" = "c_custkey" -- Укажите ограничения уникальности.
);

CREATE TABLE dates (
d_datekey DATE NOT NULL,
d_date VARCHAR(20) NOT NULL,
d_dayofweek VARCHAR(10) NOT NULL,
d_month VARCHAR(11) NOT NULL,
d_year INT(11) NOT NULL,
d_yearmonthnum INT(11) NOT NULL,
d_yearmonth VARCHAR(9) NOT NULL,
d_daynuminweek INT(11) NOT NULL,
d_daynuminmonth INT(11) NOT NULL,
d_daynuminyear INT(11) NOT NULL,
d_monthnuminyear INT(11) NOT NULL,
d_weeknuminyear INT(11) NOT NULL,
d_sellingseason VARCHAR(14) NOT NULL,
d_lastdayinweekfl INT(11) NOT NULL,
d_lastdayinmonthfl INT(11) NOT NULL,
d_holidayfl INT(11) NOT NULL,
d_weekdayfl INT(11) NOT NULL
) ENGINE=OLAP
DUPLICATE KEY(d_datekey)
DISTRIBUTED BY HASH(d_datekey) BUCKETS 1
PROPERTIES (
"unique_constraints" = "d_datekey" -- Укажите ограничения уникальности.
);

CREATE TABLE supplier (
s_suppkey INT(11) NOT NULL,
s_name VARCHAR(26) NOT NULL,
s_address VARCHAR(26) NOT NULL,
s_city VARCHAR(11) NOT NULL,
s_nation VARCHAR(16) NOT NULL,
s_region VARCHAR(13) NOT NULL,
s_phone VARCHAR(16) NOT NULL
) ENGINE=OLAP
DUPLICATE KEY(s_suppkey)
DISTRIBUTED BY HASH(s_suppkey) BUCKETS 12
PROPERTIES (
"unique_constraints" = "s_suppkey" -- Укажите ограничения уникальности.
);

CREATE TABLE part (
p_partkey INT(11) NOT NULL,
p_name VARCHAR(23) NOT NULL,
p_mfgr VARCHAR(7) NOT NULL,
p_category VARCHAR(8) NOT NULL,
p_brand VARCHAR(10) NOT NULL,
p_color VARCHAR(12) NOT NULL,
p_type VARCHAR(26) NOT NULL,
p_size TINYINT(11) NOT NULL,
p_container VARCHAR(11) NOT NULL
) ENGINE=OLAP
DUPLICATE KEY(p_partkey)
DISTRIBUTED BY HASH(p_partkey) BUCKETS 12
PROPERTIES (
"unique_constraints" = "p_partkey" -- Укажите ограничения уникальности.
);

CREATE TABLE lineorder (
lo_orderdate DATE NOT NULL, -- Укажите как NOT NULL.
lo_orderkey INT(11) NOT NULL,
lo_linenumber TINYINT NOT NULL,
lo_custkey INT(11) NOT NULL, -- Укажите как NOT NULL.
lo_partkey INT(11) NOT NULL, -- Укажите как NOT NULL.
lo_suppkey INT(11) NOT NULL, -- Укажите как NOT NULL.
lo_orderpriority VARCHAR(100) NOT NULL,
lo_shippriority TINYINT NOT NULL,
lo_quantity TINYINT NOT NULL,
lo_extendedprice INT(11) NOT NULL,
lo_ordtotalprice INT(11) NOT NULL,
lo_discount TINYINT NOT NULL,
lo_revenue INT(11) NOT NULL,
lo_supplycost INT(11) NOT NULL,
lo_tax TINYINT NOT NULL,
lo_commitdate DATE NOT NULL,
lo_shipmode VARCHAR(100) NOT NULL
) ENGINE=OLAP
DUPLICATE KEY(lo_orderdate,lo_orderkey)
PARTITION BY RANGE(lo_orderdate)
(PARTITION p1 VALUES [("0000-01-01"), ("1993-01-01")),
PARTITION p2 VALUES [("1993-01-01"), ("1994-01-01")),
PARTITION p3 VALUES [("1994-01-01"), ("1995-01-01")),
PARTITION p4 VALUES [("1995-01-01"), ("1996-01-01")),
PARTITION p5 VALUES [("1996-01-01"), ("1997-01-01")),
PARTITION p6 VALUES [("1997-01-01"), ("1998-01-01")),
PARTITION p7 VALUES [("1998-01-01"), ("1999-01-01")))
DISTRIBUTED BY HASH(lo_orderkey) BUCKETS 48
PROPERTIES (
"foreign_key_constraints" = "
(lo_custkey) REFERENCES customer(c_custkey);
(lo_partkey) REFERENCES part(p_partkey);
(lo_suppkey) REFERENCES supplier(s_suppkey)" -- Укажите внешние ключи.
);

Создадим материализованное представление lineorder_flat_mv, которое соединяет lineorder, customer, supplier, part и dates:

CREATE MATERIALIZED VIEW lineorder_flat_mv
DISTRIBUTED BY HASH(LO_ORDERDATE, LO_ORDERKEY) BUCKETS 48
PARTITION BY LO_ORDERDATE
REFRESH MANUAL
PROPERTIES (
"partition_refresh_number"="1"
)
AS SELECT /*+ SET_VAR(query_timeout = 7200) */ -- Установите тайм-аут для операции обновления.
l.LO_ORDERDATE AS LO_ORDERDATE,
l.LO_ORDERKEY AS LO_ORDERKEY,
l.LO_LINENUMBER AS LO_LINENUMBER,
l.LO_CUSTKEY AS LO_CUSTKEY,
l.LO_PARTKEY AS LO_PARTKEY,
l.LO_SUPPKEY AS LO_SUPPKEY,
l.LO_ORDERPRIORITY AS LO_ORDERPRIORITY,
l.LO_SHIPPRIORITY AS LO_SHIPPRIORITY,
l.LO_QUANTITY AS LO_QUANTITY,
l.LO_EXTENDEDPRICE AS LO_EXTENDEDPRICE,
l.LO_ORDTOTALPRICE AS LO_ORDTOTALPRICE,
l.LO_DISCOUNT AS LO_DISCOUNT,
l.LO_REVENUE AS LO_REVENUE,
l.LO_SUPPLYCOST AS LO_SUPPLYCOST,
l.LO_TAX AS LO_TAX,
l.LO_COMMITDATE AS LO_COMMITDATE,
l.LO_SHIPMODE AS LO_SHIPMODE,
c.C_NAME AS C_NAME,
c.C_ADDRESS AS C_ADDRESS,
c.C_CITY AS C_CITY,
c.C_NATION AS C_NATION,
c.C_REGION AS C_REGION,
c.C_PHONE AS C_PHONE,
c.C_MKTSEGMENT AS C_MKTSEGMENT,
s.S_NAME AS S_NAME,
s.S_ADDRESS AS S_ADDRESS,
s.S_CITY AS S_CITY,
s.S_NATION AS S_NATION,
s.S_REGION AS S_REGION,
s.S_PHONE AS S_PHONE,
p.P_NAME AS P_NAME,
p.P_MFGR AS P_MFGR,
p.P_CATEGORY AS P_CATEGORY,
p.P_BRAND AS P_BRAND,
p.P_COLOR AS P_COLOR,
p.P_TYPE AS P_TYPE,
p.P_SIZE AS P_SIZE,
p.P_CONTAINER AS P_CONTAINER,
d.D_DATE AS D_DATE,
d.D_DAYOFWEEK AS D_DAYOFWEEK,
d.D_MONTH AS D_MONTH,
d.D_YEAR AS D_YEAR,
d.D_YEARMONTHNUM AS D_YEARMONTHNUM,
d.D_YEARMONTH AS D_YEARMONTH,
d.D_DAYNUMINWEEK AS D_DAYNUMINWEEK,
d.D_DAYNUMINMONTH AS D_DAYNUMINMONTH,
d.D_DAYNUMINYEAR AS D_DAYNUMINYEAR,
d.D_MONTHNUMINYEAR AS D_MONTHNUMINYEAR,
d.D_WEEKNUMINYEAR AS D_WEEKNUMINYEAR,
d.D_SELLINGSEASON AS D_SELLINGSEASON,
d.D_LASTDAYINWEEKFL AS D_LASTDAYINWEEKFL,
d.D_LASTDAYINMONTHFL AS D_LASTDAYINMONTHFL,
d.D_HOLIDAYFL AS D_HOLIDAYFL,
d.D_WEEKDAYFL AS D_WEEKDAYFL
FROM lineorder AS l
INNER JOIN customer AS c ON c.C_CUSTKEY = l.LO_CUSTKEY
INNER JOIN supplier AS s ON s.S_SUPPKEY = l.LO_SUPPKEY
INNER JOIN part AS p ON p.P_PARTKEY = l.LO_PARTKEY
INNER JOIN dates AS d ON l.LO_ORDERDATE = d.D_DATEKEY;

SSB Q2.1 включает соединение четырех таблиц, но в нем отсутствует таблица customer по сравнению с материализованным представлением lineorder_flat_mv. В lineorder_flat_mv lineorder INNER JOIN customer по сути является соединением сохранения мощности. Следовательно, логически это соединение можно исключить, не влияя на результаты запроса. В результате Q2.1 может быть переписан с использованием lineorder_flat_mv.

SSB Q2.1:

SELECT sum(lo_revenue) AS lo_revenue, d_year, p_brand
FROM lineorder
JOIN dates ON lo_orderdate = d_datekey
JOIN part ON lo_partkey = p_partkey
JOIN supplier ON lo_suppkey = s_suppkey
WHERE p_category = 'MFGR#12' AND s_region = 'AMERICA'
GROUP BY d_year, p_brand
ORDER BY d_year, p_brand;

Его исходный план запроса и план после перезаписи следующие:

Rewrite-4

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

Перезапись Join Derivability

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

  • Сценарий первый: Соединение трех и более таблиц

    Предположим, что материализованное представление содержит Left Outer Join между таблицами t1 и t2 и Inner Join между таблицами t2 и t3. В обоих соединениях условие соединения включает столбцы из t2.

    Запрос, с другой стороны, содержит Inner Join между t1 и t2, а также Inner Join между t2 и t3. В обоих соединениях условие соединения включает столбцы из t2.

    В данном случае запрос может быть переписан с использованием материализованного представления. Это потому, что в материализованном представлении сначала выполняется Left Outer Join, а затем Inner Join. Правая таблица, сгенерированная Left Outer Join, не имеет результатов для соответствия (то есть столбцы в правой таблице являются NULL). Эти результаты затем фильтруются во время Inner Join. Поэтому логика материализованного представления и запроса эквивалентна, и запрос может быть переписан.

    Пример:

    Создадим материализованное представление join_mv5:

    CREATE MATERIALIZED VIEW join_mv5
    PARTITION BY lo_orderdate
    DISTRIBUTED BY hash(lo_orderkey)
    PROPERTIES (
    "partition_refresh_number" = "1"
    )
    AS
    SELECT lo_orderkey, lo_orderdate, lo_linenumber, lo_revenue, c_custkey, c_address, p_name
    FROM customer LEFT OUTER JOIN lineorder
    ON c_custkey = lo_custkey
    INNER JOIN part
    ON p_partkey = lo_partkey;

    join_mv5 может переписать следующий запрос:

    SELECT lo_orderkey, lo_orderdate, lo_linenumber, lo_revenue, c_custkey, c_address, p_name
    FROM customer INNER JOIN lineorder
    ON c_custkey = lo_custkey
    INNER JOIN part
    ON p_partkey = lo_partkey;

    Его исходный план запроса и план после перезаписи следующие:

    Rewrite-5

    Аналогично, если материализованное представление определено как t1 INNER JOIN t2 INNER JOIN t3, а запрос как LEFT OUTER JOIN t2 INNER JOIN t3, запрос также может быть переписан. Кроме того, эта возможность перезаписи распространяется на сценарии, включающие более трех таблиц.

  • Сценарий второй: Соединение двух таблиц

    Функция перезаписи Join Derivability, включающая две таблицы, поддерживает следующие специфические случаи:

    Rewrite-6

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

    CREATE MATERIALIZED VIEW join_mv3
    DISTRIBUTED BY hash(lo_orderkey)
    AS
    SELECT lo_orderkey, lo_linenumber, lo_revenue, c_custkey, c_address
    FROM lineorder LEFT OUTER JOIN customer
    ON lo_custkey = c_custkey;

    Следующий запрос может быть переписан с использованием join_mv3, а предикат c_custkey IS NOT NULL добавляется к переписанному результату:

    SELECT lo_orderkey, lo_linenumber, lo_revenue, c_custkey, c_address
    FROM lineorder INNER JOIN customer
    ON lo_custkey = c_custkey;

    Его исходный план запроса и план после перезаписи следующие:

    Rewrite-7

    В случае 10 запрос Left Outer Join должен включать предикат фильтрации IS NOT NULL в правой таблице, например, =, <>, >, <, <=, >=, LIKE, IN, NOT LIKE или NOT IN. Например, создадим материализованное представление следующим образом:

    CREATE MATERIALIZED VIEW join_mv4
    DISTRIBUTED BY hash(lo_orderkey)
    AS
    SELECT lo_orderkey, lo_linenumber, lo_revenue, c_custkey, c_address
    FROM lineorder INNER JOIN customer
    ON lo_custkey = c_custkey;

    join_mv4 может переписать следующий запрос, где customer.c_address = "Sb4gxKs7" является предикатом фильтрации IS NOT NULL:

    SELECT lo_orderkey, lo_linenumber, lo_revenue, c_custkey, c_address
    FROM lineorder LEFT OUTER JOIN customer
    ON lo_custkey = c_custkey
    WHERE customer.c_address = "Sb4gxKs7";

    Его исходный план запроса и план после перезаписи следующие:

    Rewrite-8

Перезапись агрегаций

Асинхронное материализованное представление Selena поддерживает перезапись многотабличных агрегатных запросов со всеми доступными агрегатными функциями, включая bitmap_union, hll_union и percentile_union. Например, создайте материализованное представление следующим образом:

CREATE MATERIALIZED VIEW agg_mv1
DISTRIBUTED BY hash(lo_orderkey)
AS
SELECT
lo_orderkey,
lo_linenumber,
c_name,
sum(lo_revenue) AS total_revenue,
max(lo_discount) AS max_discount
FROM lineorder INNER JOIN customer
ON lo_custkey = c_custkey
GROUP BY lo_orderkey, lo_linenumber, c_name;

Оно может переписать следующий запрос:

SELECT 
lo_orderkey,
lo_linenumber,
c_name,
sum(lo_revenue) AS total_revenue,
max(lo_discount) AS max_discount
FROM lineorder INNER JOIN customer
ON lo_custkey = c_custkey
GROUP BY lo_orderkey, lo_linenumber, c_name;

Его исходный план запроса и план после перезаписи следующие:

Rewrite-9

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

Перезапись Aggregation Rollup

Selena поддерживает перезапись запросов с Aggregation Rollup, то есть Selena может переписывать агрегатные запросы с предложением GROUP BY a, используя асинхронное материализованное представление, созданное с предложением GROUP BY a,b. Например, следующий запрос может быть переписан с использованием agg_mv1:

SELECT 
lo_orderkey,
c_name,
sum(lo_revenue) AS total_revenue,
max(lo_discount) AS max_discount
FROM lineorder INNER JOIN customer
ON lo_custkey = c_custkey
GROUP BY lo_orderkey, c_name;

Его исходный план запроса и план после перезаписи следующие:

Rewrite-10

ПРИМЕЧАНИЕ

В настоящее время перезапись grouping set, grouping set with rollup или grouping set with cube не поддерживается.

Только определенные агрегатные функции поддерживают перезапись запросов с Aggregate Rollup. В предыдущем примере, если материализованное представление order_agg_mv использует count(distinct client_id) вместо bitmap_union(to_bitmap(client_id)), Selena не может переписать запросы с Aggregate Rollup.

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

Агрегатная функция поддерживается в исходных запросахФункция поддерживает Aggregate Rollup в материализованном представлении
sumsum
countcount
minmin
maxmax
avgsum / count
bitmap_union, bitmap_union_count, count(distinct)bitmap_union
hll_raw_agg, hll_union_agg, ndv, approx_count_distincthll_union
percentile_approx, percentile_unionpercentile_union

Агрегаты DISTINCT без соответствующего столбца GROUP BY не могут быть переписаны с помощью Aggregate Rollup. Однако, начиная с Selena v3.1, если запрос с агрегатной функцией Aggregate Rollup DISTINCT не имеет столбца GROUP BY, но имеет предикат равенства, он также может быть переписан соответствующим материализованным представлением, поскольку Selena может преобразовать предикаты равенства в константное выражение GROUP BY.

В следующем примере Selena может переписать запрос с помощью материализованного представления order_agg_mv1.

CREATE MATERIALIZED VIEW order_agg_mv1
DISTRIBUTED BY HASH(`order_id`) BUCKETS 12
REFRESH ASYNC START('2022-09-01 10:00:00') EVERY (interval 1 day)
AS
SELECT
order_date,
count(distinct client_id)
FROM order_list
GROUP BY order_date;


-- Запрос
SELECT
order_date,
count(distinct client_id)
FROM order_list WHERE order_date='2023-07-03';

Проталкивание агрегации

Начиная с v3.3.0 Selena поддерживает проталкивание агрегации для перезаписи запросов материализованных представлений. Когда эта функция включена, агрегатные функции будут проталкиваться к Scan Operator во время выполнения запроса и переписываться материализованным представлением до выполнения Join Operator. Это смягчит расширение данных, вызванное Join, и тем самым улучшит производительность запросов.

Эта функция отключена по умолчанию. Чтобы включить эту функцию, вы должны установить системную переменную enable_materialized_view_agg_pushdown_rewrite в true.

Предположим, что вы хотите ускорить следующий запрос SQL1, основанный на SSB:

-- SQL1
SELECT
LO_ORDERDATE, sum(LO_REVENUE), max(LO_REVENUE), count(distinct LO_REVENUE)
FROM lineorder l JOIN dates d
ON l.LO_ORDERDATE = d.d_date
GROUP BY LO_ORDERDATE
ORDER BY LO_ORDERDATE;

SQL1 состоит из агрегаций на таблице lineorder и Join lineorder и dates. Поскольку агрегации происходят внутри lineorder, а Join с dates используется только для фильтрации данных, SQL1 логически эквивалентен следующему SQL2:

-- SQL2
SELECT
LO_ORDERDATE, sum(sum1), max(max1), bitmap_union_count(bitmap1)
FROM
(SELECT
LO_ORDERDATE, sum(LO_REVENUE) AS sum1, max(LO_REVENUE) AS max1, bitmap_union(to_bitmap(LO_REVENUE)) AS bitmap1
FROM lineorder
GROUP BY LO_ORDERDATE) l JOIN dates d
ON l.LO_ORDERDATE = d.d_date
GROUP BY LO_ORDERDATE
ORDER BY LO_ORDERDATE;

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

-- Создаем материализованное представление mv0
CREATE MATERIALIZED VIEW mv0 REFRESH MANUAL AS
SELECT
LO_ORDERDATE,
sum(LO_REVENUE) AS sum1,
max(LO_REVENUE) AS max1,
bitmap_union(to_bitmap(LO_REVENUE)) AS bitmap1
FROM lineorder
GROUP BY LO_ORDERDATE;

-- Включаем проталкивание агрегаций для перезаписи запросов материализованных представлений
SET enable_materialized_view_agg_pushdown_rewrite=true;

Затем SQL1 будет переписан и ускорен материализованным представлением. Он переписывается в следующий запрос:

SELECT 
LO_ORDERDATE, sum(sum1), max(max1), bitmap_union_count(bitmap1)
FROM
(SELECT LO_ORDERDATE, sum1, max1, bitmap1 FROM mv0) l JOIN dates d
ON l.LO_ORDERDATE = d.d_date
GROUP BY LO_ORDERDATE
ORDER BY LO_ORDERDATE;

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

  • MIN
  • MAX
  • COUNT
  • COUNT DISTINCT
  • SUM
  • BITMAP_UNION
  • HLL_UNION
  • PERCENTILE_UNION
  • BITMAP_AGG
  • ARRAY_AGG_DISTINCT
примечание
  • После проталкивания агрегатные функции должны быть свернуты для соответствия исходной семантике. Для получения дополнительных инструкций по Aggregation Rollup см. Aggregation Rollup Rewrite.
  • Проталкивание агрегации поддерживает перезапись Rollup Count Distinct на основе функций Bitmap или HLL.
  • Проталкивание агрегации поддерживает только проталкивание агрегатных функций к Scan Operator перед операторами Join, Filter или Where.
  • Проталкивание агрегации поддерживает только перезапись запросов и ускорение на основе материализованного представления, построенного на одной таблице.

Перезапись COUNT DISTINCT

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

CREATE MATERIALIZED VIEW distinct_mv
DISTRIBUTED BY hash(lo_orderkey)
AS
SELECT lo_orderkey, bitmap_union(to_bitmap(lo_custkey)) AS distinct_customer
FROM lineorder
GROUP BY lo_orderkey;

Оно может переписать следующий запрос:

SELECT lo_orderkey, count(distinct lo_custkey) 
FROM lineorder
GROUP BY lo_orderkey;

Перезапись вложенных материализованных представлений

Selena поддерживает перезапись запросов с использованием вложенных материализованных представлений. Например, создадим материализованные представления join_mv2, agg_mv2 и agg_mv3 следующим образом:

CREATE MATERIALIZED VIEW join_mv2
DISTRIBUTED BY hash(lo_orderkey)
AS
SELECT lo_orderkey, lo_linenumber, lo_revenue, c_name, c_address
FROM lineorder INNER JOIN customer
ON lo_custkey = c_custkey;


CREATE MATERIALIZED VIEW agg_mv2
DISTRIBUTED BY hash(lo_orderkey)
AS
SELECT
lo_orderkey,
lo_linenumber,
c_name,
sum(lo_revenue) AS total_revenue,
max(lo_discount) AS max_discount
FROM join_mv2
GROUP BY lo_orderkey, lo_linenumber, c_name;

CREATE MATERIALIZED VIEW agg_mv3
DISTRIBUTED BY hash(lo_orderkey)
AS
SELECT
lo_orderkey,
sum(total_revenue) AS total_revenue,
max(max_discount) AS max_discount
FROM agg_mv2
GROUP BY lo_orderkey;

Их связь следующая:

Rewrite-11

agg_mv3 может переписать следующий запрос:

SELECT 
lo_orderkey,
sum(lo_revenue) AS total_revenue,
max(lo_discount) AS max_discount
FROM lineorder INNER JOIN customer
ON lo_custkey = c_custkey
GROUP BY lo_orderkey;

Его исходный план запроса и план после перезаписи следующие:

Rewrite-12

Перезапись Union

Перезапись Predicate Union

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

Например, создадим материализованное представление следующим образом:

CREATE MATERIALIZED VIEW agg_mv4
DISTRIBUTED BY hash(lo_orderkey)
AS
SELECT
lo_orderkey,
sum(lo_revenue) AS total_revenue,
max(lo_discount) AS max_discount
FROM lineorder
WHERE lo_orderkey < 300000000
GROUP BY lo_orderkey;

Оно может переписать следующий запрос:

select 
lo_orderkey,
sum(lo_revenue) AS total_revenue,
max(lo_discount) AS max_discount
FROM lineorder
GROUP BY lo_orderkey;

Его исходный план запроса и план после перезаписи следующие:

Rewrite-13

В данном контексте agg_mv5 содержит данные, где lo_orderkey < 300000000. Данные, где lo_orderkey >= 300000000, получаются непосредственно из базовой таблицы lineorder. Наконец, эти два набора данных объединяются с помощью операции UNION, а затем агрегируются для получения окончательного результата.

Перезапись Partition Union

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

Например, рассмотрим следующее материализованное представление agg_mv4. Его базовая таблица lineorder в настоящее время содержит разделы с p1 по p7, а материализованное представление также содержит разделы с p1 по p7.

CREATE MATERIALIZED VIEW agg_mv5
DISTRIBUTED BY hash(lo_orderkey)
PARTITION BY RANGE(lo_orderdate)
REFRESH MANUAL
AS
SELECT
lo_orderdate,
lo_orderkey,
sum(lo_revenue) AS total_revenue,
max(lo_discount) AS max_discount
FROM lineorder
GROUP BY lo_orderkey;

Если к lineorder добавляется новый раздел p8 с диапазоном разделов [("19990101"), ("20000101")), следующий запрос может быть переписан с использованием операции UNION:

SELECT 
lo_orderdate,
lo_orderkey,
sum(lo_revenue) AS total_revenue,
max(lo_discount) AS max_discount
FROM lineorder
GROUP BY lo_orderkey;

Его исходный план запроса и план после перезаписи следующие:

Rewrite-14

Как показано выше, agg_mv5 содержит данные из разделов с p1 по p7, а данные из раздела p8 запрашиваются непосредственно из lineorder. Наконец, эти два набора данных объединяются с помощью операции UNION.

Перезапись материализованных представлений на основе представлений

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

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

Основы

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

Для решения этой проблемы Selena вводит новый оператор - LogicalViewScanOperator, чтобы упростить структуру дерева плана выполнения без переписывания запроса. Этот оператор стремится сопоставить дерево плана выполнения с шаблоном SPJG, тем самым облегчая перезапись запросов.

Следующий пример приводит запрос с подзапросом AGGREGATE, представление, построенное на основе подзапроса, переписанный запрос на основе представления и материализованное представление, построенное на основе представления:

-- Оригинальный запрос:
SELECT
v1.a,
t2.b,
v1.total
FROM(
SELECT
a,
sum(c) AS total
FROM t1
GROUP BY a
) v1
INNER JOIN t2 ON v1.a = t2.a;

-- Представление:
CREATE VIEW view_1 AS
SELECT
t1.a,
sum(t1.c) AS total
FROM t1
GROUP BY t1.a;

-- Переписанный запрос:
SELECT
v1.a,
t2.b,
v1.total
FROM view_1 v1
JOIN t2 ON v1.a = t2.a;

-- Материализованное представление:
CREATE MATERIALIZED VIEW mv1
DISTRIBUTED BY hash(a)
REFRESH MANUAL
AS
SELECT
v1.a,
t2.b,
v1.total
FROM view_1 v1
JOIN t2 ON v1.a = t2.a;

План выполнения исходного запроса, как показано слева на следующей диаграмме, не соответствует шаблону SPJG из-за LogicalAggregateOperator внутри JOIN. Selena не поддерживает перезапись запросов для таких случаев. Однако, определив представление на основе подзапроса, исходный запрос можно переписать в запрос к представлению. С помощью LogicalViewScanOperator Selena может перенести несоответствующую часть в шаблон SPJG, тем самым позволяя перезапись запросов в этом обстоятельстве.

img

Использование

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

Чтобы включить эту функцию, вы должны установить следующую переменную:

SET enable_view_based_mv_rewrite = true;

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

Перезапись запросов с использованием материализованных представлений на основе одного представления

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

Например, вы можете построить следующее представление и материализованное представление для TPC-H Query 18:

CREATE VIEW q18_view
AS
SELECT
c_name,
c_custkey,
o_orderkey,
o_orderdate,
o_totalprice,
sum(l_quantity)
FROM
customer,
orders,
lineitem
WHERE
o_orderkey IN (
SELECT
l_orderkey
FROM
lineitem
GROUP BY
l_orderkey having
sum(l_quantity) > 315
)
AND c_custkey = o_custkey
AND o_orderkey = l_orderkey
GROUP BY
c_name,
c_custkey,
o_orderkey,
o_orderdate,
o_totalprice;

CREATE MATERIALIZED VIEW q18_mv
DISTRIBUTED BY hash(c_custkey, o_orderkey)
REFRESH MANUAL
AS
SELECT * FROM q18_view;

Материализованное представление может переписать следующие запросы:

mysql> EXPLAIN LOGICAL SELECT * FROM q18_view;
+-------------------------------------------------------------------------------------------------------+
| Explain String |
+-------------------------------------------------------------------------------------------------------+
| - Output => [2:c_name, 1:c_custkey, 9:o_orderkey, 10:o_orderdate, 13:o_totalprice, 52:sum] |
| - SCAN [q18_mv] => [1:c_custkey, 2:c_name, 52:sum, 9:o_orderkey, 10:o_orderdate, 13:o_totalprice] |
| MaterializedView: true |
| Estimates: {row: 9, cpu: 486.00, memory: 0.00, network: 0.00, cost: 243.00} |
| partitionRatio: 1/1, tabletRatio: 96/96 |
| 1:c_custkey := 60:c_custkey |
| 2:c_name := 59:c_name |
| 52:sum := 64:sum(l_quantity) |
| 9:o_orderkey := 61:o_orderkey |
| 10:o_orderdate := 62:o_orderdate |
| 13:o_totalprice := 63:o_totalprice |
+-------------------------------------------------------------------------------------------------------+
mysql> EXPLAIN LOGICAL SELECT c_name, sum(`sum(l_quantity)`) FROM q18_view GROUP BY c_name;
+-----------------------------------------------------------------------------------------------------+
| Explain String |
+-----------------------------------------------------------------------------------------------------+
| - Output => [2:c_name, 59:sum] |
| - AGGREGATE(GLOBAL) [2:c_name] |
| Estimates: {row: 9, cpu: 306.00, memory: 306.00, network: 0.00, cost: 1071.00} |
| 59:sum := sum(59:sum) |
| - EXCHANGE(SHUFFLE) [2] |
| Estimates: {row: 9, cpu: 30.60, memory: 0.00, network: 30.60, cost: 306.00} |
| - AGGREGATE(LOCAL) [2:c_name] |
| Estimates: {row: 9, cpu: 61.20, memory: 30.60, network: 0.00, cost: 244.80} |
| 59:sum := sum(52:sum) |
| - SCAN [q18_mv] => [2:c_name, 52:sum] |
| MaterializedView: true |
| Estimates: {row: 9, cpu: 306.00, memory: 0.00, network: 0.00, cost: 153.00} |
| partitionRatio: 1/1, tabletRatio: 96/96 |
| 2:c_name := 60:c_name |
| 52:sum := 65:sum(l_quantity) |
+-----------------------------------------------------------------------------------------------------+

Rewrite queries with JOIN using view-based materialized views

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

Например, вы можете создать следующие представления и материализованное представление:

CREATE VIEW view_1 AS
SELECT
l_partkey,
l_suppkey,
sum(l_quantity) AS total_quantity
FROM lineitem
GROUP BY
l_partkey,
l_suppkey;


CREATE VIEW view_2 AS
SELECT
l_partkey,
l_suppkey,
sum(l_tax) AS total_tax
FROM lineitem
GROUP BY
l_partkey,
l_suppkey;


CREATE MATERIALIZED VIEW mv_1
DISTRIBUTED BY hash(l_partkey, l_suppkey)
REFRESH MANUAL AS
SELECT
v1.l_partkey,
v2.l_suppkey,
total_quantity,
total_tax
FROM view_1 v1
JOIN view_2 v2 ON v1.l_partkey = v2.l_partkey
AND v1.l_suppkey = v2.l_suppkey;

Материализованное представление может переписать следующие запросы:

mysql>  EXPLAIN LOGICAL
-> SELECT v1.l_partkey,
-> v2.l_suppkey,
-> total_quantity,
-> total_tax
-> FROM view_1 v1
-> JOIN view_2 v2 ON v1.l_partkey = v2.l_partkey
-> AND v1.l_suppkey = v2.l_suppkey;
+--------------------------------------------------------------------------------------------------------+
| Explain String |
+--------------------------------------------------------------------------------------------------------+
| - Output => [4:l_partkey, 25:l_suppkey, 17:sum, 37:sum] |
| - SCAN [mv_1] => [17:sum, 4:l_partkey, 37:sum, 25:l_suppkey] |
| MaterializedView: true |
| Estimates: {row: 799541, cpu: 31981640.00, memory: 0.00, network: 0.00, cost: 15990820.00} |
| partitionRatio: 1/1, tabletRatio: 96/96 |
| 17:sum := 43:total_quantity |
| 4:l_partkey := 41:l_partkey |
| 37:sum := 44:total_tax |
| 25:l_suppkey := 42:l_suppkey |
+--------------------------------------------------------------------------------------------------------+
mysql> EXPLAIN LOGICAL
-> SELECT v1.l_partkey,
-> sum(total_quantity),
-> sum(total_tax)
-> FROM view_1 v1
-> JOIN view_2 v2 ON v1.l_partkey = v2.l_partkey
-> AND v1.l_suppkey = v2.l_suppkey
-> group by v1.l_partkey;
+--------------------------------------------------------------------------------------------------------------------+
| Explain String |
+--------------------------------------------------------------------------------------------------------------------+
| - Output => [4:l_partkey, 41:sum, 42:sum] |
| - AGGREGATE(GLOBAL) [4:l_partkey] |
| Estimates: {row: 196099, cpu: 4896864.00, memory: 3921980.00, network: 0.00, cost: 29521223.20} |
| 41:sum := sum(41:sum) |
| 42:sum := sum(42:sum) |
| - EXCHANGE(SHUFFLE) [4] |
| Estimates: {row: 136024, cpu: 489686.40, memory: 0.00, network: 489686.40, cost: 19228831.20} |
| - AGGREGATE(LOCAL) [4:l_partkey] |
| Estimates: {row: 136024, cpu: 5756695.20, memory: 489686.40, network: 0.00, cost: 18249458.40} |
| 41:sum := sum(17:sum) |
| 42:sum := sum(37:sum) |
| - SCAN [mv_1] => [17:sum, 4:l_partkey, 37:sum] |
| MaterializedView: true |
| Estimates: {row: 799541, cpu: 28783476.00, memory: 0.00, network: 0.00, cost: 14391738.00} |
| partitionRatio: 1/1, tabletRatio: 96/96 |
| 17:sum := 45:total_quantity |
| 4:l_partkey := 43:l_partkey |
| 37:sum := 46:total_tax |
+--------------------------------------------------------------------------------------------------------------------+

Перезапись запросов с использованием материализованных представлений, построенных на представлениях внешних таблиц

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

Перезапись материализованных представлений на основе external catalog

Selena поддерживает создание асинхронных материализованных представлений на Hive catalog, Hudi catalog, Iceberg catalog и Paimon catalog и прозрачную перезапись запросов с ними.

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

Начиная с версии 1.5.0 Selena поддерживает перезапись материализованных представлений на основе текста, что значительно расширяет возможности перезаписи запросов.

Основы

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

Перезапись материализованных представлений на основе текста не ограничивается операторами SPJG-типа. Она также поддерживает операторы Union, Window, Order, Limit и CTE.

Использование

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

Параметр конфигурации FE enable_materialized_view_text_based_rewrite контролирует, строить ли абстрактное синтаксическое дерево при создании асинхронного материализованного представления. Эта функция также включена по умолчанию. Установка этого параметра в false отключит перезапись материализованных представлений на основе текста на системном уровне.

Переменная materialized_view_subuqery_text_match_max_count контролирует максимальное количество сравнений абстрактных синтаксических деревьев материализованного представления и подзапросов. Значение по умолчанию 4. Увеличение этого значения также увеличит время работы оптимизатора.

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

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

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

  • Исходный запрос соответствует определению материализованного представления.
  • Подзапрос исходного запроса соответствует определению материализованного представления.

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

к сведению
  • Рекомендуется инкапсулировать запрос для сопоставления в подзапрос исходного запроса.
  • Пожалуйста, не инкапсулируйте предложения ORDER BY в определение материализованного представления или подзапрос исходного запроса. В противном случае запрос не сможет быть переписан, поскольку предложения ORDER BY в подзапросе по умолчанию исключаются.

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

CREATE MATERIALIZED VIEW mv1 REFRESH MANUAL AS
SELECT
user_id,
count(1)
FROM (
SELECT
user_id,
time,
bitmap_union(to_bitmap(tag_id)) AS a
FROM user_tags
GROUP BY
user_id,
time) t
GROUP BY user_id;

Материализованное представление может переписать следующие запросы:

SELECT 
user_id,
count(1)
FROM (
SELECT
user_id,
time,
bitmap_union(to_bitmap(tag_id)) AS a
FROM user_tags
GROUP BY
user_id,
time) t
GROUP BY user_id;
SELECT count(1)
FROM

SELECT
user_id,
count(1)
FROM (
SELECT
user_id,
time,
bitmap_union(to_bitmap(tag_id)) AS a
FROM user_tags
GROUP BY
user_id,
time) t
GROUP BY user_id
)m;

Однако материализованное представление не может переписать следующий запрос, поскольку исходный запрос содержит предложение ORDER BY:

SELECT 
user_id,
count(1)
FROM (
SELECT
user_id,
time,
bitmap_union(to_bitmap(tag_id)) AS a
FROM user_tags
GROUP BY
user_id,
time) t
GROUP BY user_id
ORDER BY user_id;

Настройка перезаписи запросов

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

VariableDefaultDescription
enable_materialized_view_union_rewritetrueЛогическое значение для управления включением перезаписи Union запросов материализованных представлений.
enable_rule_based_materialized_view_rewritetrueЛогическое значение для управления включением перезаписи запросов материализованных представлений на основе правил. Эта переменная главным образом используется в перезаписи запросов к одной таблице.
nested_mv_rewrite_max_level3Максимальное количество уровней вложенных материализованных представлений, которые могут использоваться для перезаписи запросов. Тип: INT. Диапазон: [1, +∞). Значение 1 означает, что материализованные представления, созданные на основе других материализованных представлений, не будут использоваться для перезаписи запросов.

Проверка перезаписи запроса

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

mysql> EXPLAIN SELECT 
order_id, sum(goods.price) AS total
FROM order_list INNER JOIN goods
ON goods.item_id1 = order_list.item_id2
GROUP BY order_id;
+------------------------------------+
| Explain String |
+------------------------------------+
| PLAN FRAGMENT 0 |
| OUTPUT EXPRS:1: order_id | 8: sum |
| PARTITION: RANDOM |
| |
| RESULT SINK |
| |
| 1:Project |
| | <slot 1> : 9: order_id |
| | <slot 8> : 10: total |
| | |
| 0:OlapScanNode |
| TABLE: order_mv |
| PREAGGREGATION: ON |
| partitions=1/1 |
| rollup: order_mv |
| tabletRatio=0/12 |
| tabletList= |
| cardinality=3 |
| avgRowSize=4.0 |
| numNodes=0 |
+------------------------------------+
20 rows in set (0.01 sec)

Отключение перезаписи запросов

По умолчанию Selena включает перезапись запросов для асинхронных материализованных представлений, созданных на основе Default Catalog. Вы можете отключить эту функцию, установив переменную сессии enable_materialized_view_rewrite в false.

Для асинхронных материализованных представлений, созданных на основе external catalog, вы можете отключить эту функцию, установив свойство материализованного представления force_external_table_query_rewrite в false, используя ALTER MATERIALIZED VIEW.

Ограничения

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

  • Selena не поддерживает перезапись запросов с недетерминированными функциями, включая rand, random, uuid и sleep.
  • Selena не поддерживает перезапись запросов с оконными функциями.
  • Материализованные представления, определенные операторами, содержащими LIMIT, ORDER BY, UNION, EXCEPT, INTERSECT, MINUS, GROUPING SETS, WITH CUBE или WITH ROLLUP, не могут использоваться для перезаписи запросов.
  • Строгая согласованность результатов запросов не гарантируется между базовыми таблицами и материализованными представлениями, построенными на external catalog.
  • Асинхронные материализованные представления, созданные на базовых таблицах в JDBC catalog, не поддерживают перезапись запросов.

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

  • В настоящее время Selena не поддерживает перезапись Partition Union.

  • Перезапись запросов не поддерживается, если представление содержит случайные функции, включая rand(), random(), uuid() и sleep().

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

  • Представления, которые используются для создания материализованного представления, должны содержать по крайней мере один столбец следующих типов данных: целочисленные типы, типы даты и строковые типы. Например, вы не можете создать материализованное представление, запрашивающее представление, поскольку total_cost - это столбец типа DOUBLE.

    CREATE VIEW v1
    AS
    SELECT sum(cost) AS total_cost
    FROM t1;