StarRocks提供了開箱即用的資料湖查詢功能,非常適用於對湖中的資料進行探查式查詢分析。通過使用非同步物化視圖,您可以為資料湖中的報表和應用實現更高的並發,以及更好的效能。本文為您介紹如何使用StarRocks的非同步物化視圖來最佳化資料湖中的查詢效能。
適用情境
StarRocks支援基於External Catalog,如Hive Catalog、Iceberg Catalog、Hudi Catalog、JDBC Catalog和Paimon Catalog構建非同步物化視圖。基於External Catalog的物化視圖適用於以下情境。
資料湖報表的透明加速
為了確保資料湖報表的查詢效能,資料工程師通常需要與資料分析師緊密合作,研究報告加速層的構建邏輯。如果加速層需求更新,他們必須相應地更新構建邏輯、執行計畫和查詢語句。通過物化視圖的查詢改寫能力,可以使使用者不感知報表加速過程。當識別出慢查詢時,資料工程師可以分析慢查詢的模式並按需建立物化視圖。然後,上層查詢會被智能改寫,並通過物化視圖透明加速,從而實現在不修改業務應用的邏輯或查詢語句情況下,快速改善查詢效能。
即時資料與離線資料關聯的增量計算
假設您的業務應用需要將StarRocks本地表中的即時資料與資料湖中的歷史資料關聯起來以進行增量計算。在這種情況下,物化視圖可以提供一個簡單的解決方案。例如,如果即時事實表是StarRocks中的本地表,而維度資料表儲存在資料湖中,您可以通過構建物化視圖將本地表與外部資料源中的表關聯起來,輕鬆進行增量計算。
指標層的快速搭建
在處理高維度資料時,計算和處理指標可能會遇到挑戰。您可以使用物化視圖進行資料預彙總和上卷,以建立一個相對輕量級的指標層。此外,您還可以利用物化視圖自動重新整理的特性,進一步降低指標計算的複雜性。
功能對比
物化視圖、Data Cache和StarRocks中的本地表都是實現顯著查詢效能提升的有效方法。下表比較了它們的主要區別。
對比項 | Data Cache | 物化視圖 | 本地表 |
資料匯入和更新 | 查詢會自動觸發資料緩衝 | 自動觸發重新整理任務 | 支援各種匯入方法,但需要手動維護匯入任務 |
資料緩衝粒度 |
| 儲存預計算的查詢結果 | 基於表定義儲存資料 |
查詢效能 | Data Cache ≤ 物化視圖 = 本地表 | ||
查詢語句 |
|
| 需要修改查詢語句以查詢本地表 |
與直接查詢資料湖資料或將資料匯入到本地表中相比,物化視圖提供了幾個獨特的優勢:
本機存放區加速:物化視圖可以利用StarRocks的本機存放區加速優勢,如索引、分區分桶和Colocate Group,從而相較直接從資料湖查詢資料具有更好的查詢效能。
無需維護載入任務:物化視圖通過自動重新整理任務透明地更新資料,無需維護匯入任務。此外,基於Hive、Iceberg和Paimon Catalog的物化視圖可以檢測資料更改並在分區層級執行增量重新整理。
智能查詢改寫:查詢可以被透明改寫至物化視圖,無需修改應用使用的查詢語句即可加速查詢。
使用建議
建議在以下情況下使用物化視圖:
在啟用了Data Cache的情況下,查詢效能仍不符合您對查詢延遲和並發性的要求。
查詢涉及可複用的部分,如固定的彙總方式、Join模式。
資料以分區方式組織,而查詢彙總度較高(例如按天彙總)。
在以下情況下,建議優先通過Data Cache來實現加速:
查詢沒有大量可複用的部分,並且可能涉及資料湖中的任何資料。
遠程儲存存在顯著的波動或不穩定性,可能會對訪問產生潛在影響。
建立基於External Catalog的物化視圖
在External Catalog中的表上建立物化視圖與在StarRocks本地表上建立物化視圖類似。您只需根據正在使用的資料來源設定合適的重新整理策略,並手動啟用External Catalog物化視圖的查詢改寫功能。
選擇合適的重新整理策略
目前,StarRocks無法檢測Hudi Catalog中的分區層級資料更改。因此,一旦觸發重新整理任務,將執行全量重新整理。
對於Hive Catalog、Iceberg Catalog(從v3.1.4版本起)、JDBC Catalog(從v3.1.4版本起,且僅支援MySQL Range分區)和Paimon Catalog(從v3.2.1版本起),StarRocks支援檢測分區層級資料更改。從而,StarRocks可以:
僅重新整理資料有更改的分區,避免全量重新整理,減少重新整理導致的資源消耗。
在查詢改寫期間在一定程度上確保資料一致性。如果資料湖中的基表發生資料更改,查詢將不會被改寫為使用物化視圖。
您仍然可以選擇在建立物化視圖時通過設定屬性mv_rewrite_staleness_second來容忍一定程度的資料不一致。
請注意,如需按照分區重新整理,物化視圖的分區鍵必須包含在基表的分區鍵中。
從v3.2.3版本開始,StarRocks支援在使用Partition Transforms的Iceberg表上建立分區物化視圖,物化視圖將根據變換後的列進行分區。目前,僅支援使用identity、year、month、day或hourTransform的Iceberg表。
以下樣本展示了一個使用dayTransform的Iceberg表的定義,並在該表上建立了一個分區對齊的物化視圖:
-- Iceberg表定義。
CREATE TABLE spark_catalog.test_db.iceberg_sample_datetime_day (
id BIGINT,
data STRING,
category STRING,
ts TIMESTAMP)
USING iceberg
PARTITIONED BY (days(ts))
-- 基於以上Iceberg表建立物化視圖。
CREATE MATERIALIZED VIEW `test_iceberg_datetime_day_mv` (`id`, `data`, `category`, `ts`)
PARTITION BY (`ts`)
DISTRIBUTED BY HASH(`id`)
REFRESH MANUAL
AS
SELECT
`iceberg_sample_datetime_day`.`id`,
`iceberg_sample_datetime_day`.`data`,
`iceberg_sample_datetime_day`.`category`,
`iceberg_sample_datetime_day`.`ts`
FROM `iceberg`.`test`.`iceberg_sample_datetime_day`;對於Hive Catalog,您可以啟用Hive中繼資料快取重新整理功能,允許StarRocks在分區層級檢測資料更改。啟用此功能後,StarRocks定期訪問Hive中繼資料存放區服務(HMS)或AWS Glue,以檢查最近查詢的熱資料的中繼資料資訊。
配置項
要啟用Hive中繼資料快取重新整理功能,您可以使用ADMIN SET FRONTEND CONFIG設定以下FE動態配置項。文法如下。
ADMIN SET FRONTEND CONFIG ("key" = "value")配置名稱 | 預設值 | 描述 |
|
| 是否開啟Hive中繼資料快取周期性重新整理。開啟後,StarRocks會輪詢Hive叢集的中繼資料服務(HMS或AWS Glue),並重新整理經常訪問的Hive外部資料目錄的中繼資料快取,以感知資料更新。 |
| 600000(10分鐘) | 接連兩次Hive中繼資料快取重新整理之間的間隔。單位:毫秒。 |
| 86400(24小時) | Hive中繼資料快取重新整理任務到期時間。對於已被訪問過的Hive Catalog,如果超過該時間沒有被訪問,則停止重新整理其中繼資料快取。對於未被訪問過的Hive Catalog,StarRocks不會重新整理其中繼資料快取。單位:秒。 |
對於Iceberg Catalog,從v3.1.4版本開始,StarRocks支援檢測分區層級的資料更改,當前只支援Iceberg V1表。
啟用External Catalog物化視圖的查詢改寫
由於不保證資料的強一致性,StarRocks預設禁用Hudi和JDBC Catalog物化視圖的查詢改寫功能。您可以通過在建立物化視圖時將Propertyforce_external_table_query_rewrite設定為true來啟用此功能。對於基於Hive Catalog中的表建立的物化視圖,查詢改寫功能預設開啟。在涉及查詢改寫的情況下,如果您使用非常複雜的查詢語句來構建物化視圖,我們建議您拆分查詢語句並以嵌套方式構建多個簡單的物化視圖。嵌套的物化視圖更加靈活,可以適應更廣泛的查詢模式。
樣本如下。
CREATE MATERIALIZED VIEW ex_mv_par_tbl
PARTITION BY emp_date
DISTRIBUTED BY hash(empid)
PROPERTIES (
"force_external_table_query_rewrite" = "true"
)
AS
SELECT empid, deptno, emp_date
FROM `hudi_catalog`.`emp_db`.`emps_par_tbl`
WHERE empid < 5;最佳實務
在實際業務情境中,您可以通過分析Audit Log或大查詢日誌來識別執行較慢、資源消耗較高的查詢。您還可以使用Query Profile來精確定位查詢緩慢的特定階段。以下為通過物化視圖提高資料湖查詢效能的說明和樣本。
案例一:加速資料湖中的Join計算
您可以使用物化視圖來加速資料湖中的Join查詢。
假設以下Hive catalog上的查詢為慢查詢。
--Q1
SELECT SUM(lo_extendedprice * lo_discount) AS REVENUE
FROM hive.ssb_1g_csv.lineorder, hive.ssb_1g_csv.dates
WHERE
lo_orderdate = d_datekey
AND d_year = 1993
AND lo_discount BETWEEN 1 AND 3
AND lo_quantity < 25;
--Q2
SELECT SUM(lo_extendedprice * lo_discount) AS REVENUE
FROM hive.ssb_1g_csv.lineorder, hive.ssb_1g_csv.dates
WHERE
lo_orderdate = d_datekey
AND d_yearmonth = 'Jan1994'
AND lo_discount BETWEEN 4 AND 6
AND lo_quantity BETWEEN 26 AND 35;
--Q3
SELECT SUM(lo_revenue), d_year, p_brand
FROM hive.ssb_1g_csv.lineorder, hive.ssb_1g_csv.dates, hive.ssb_1g_csv.part, hive.ssb_1g_csv.supplier
WHERE
lo_orderdate = d_datekey
AND lo_partkey = p_partkey
AND lo_suppkey = s_suppkey
AND p_brand BETWEEN 'MFGR#2221' AND 'MFGR#2228'
AND s_region = 'ASIA'
GROUP BY d_year, p_brand
ORDER BY d_year, p_brand;通過分析查詢概要,您可能會注意到查詢執行時間主要花費在表lineorder與其他維度資料表在列lo_orderdate上的Hash Join上。
此處,Q1和Q2在Joinlineorder和dates後執行彙總,而Q3在Joinlineorder、dates、part和supplier後執行彙總。
因此,您可以利用StarRocks的View Delta Join改寫能力來構建物化視圖,對lineorder、dates、part和supplier進行Join。
CREATE MATERIALIZED VIEW lineorder_flat_mv
DISTRIBUTED BY HASH(LO_ORDERDATE, LO_ORDERKEY) BUCKETS 48
PARTITION BY LO_ORDERDATE
REFRESH ASYNC EVERY(INTERVAL 1 DAY)
PROPERTIES (
-- 指定唯一約束。
"unique_constraints" = "
hive.ssb_1g_csv.supplier.s_suppkey;
hive.ssb_1g_csv.part.p_partkey;
hive.ssb_1g_csv.dates.d_datekey",
-- 指定外鍵約束。
"foreign_key_constraints" = "
hive.ssb_1g_csv.lineorder(lo_partkey) REFERENCES hive.ssb_1g_csv.part(p_partkey);
hive.ssb_1g_csv.lineorder(lo_suppkey) REFERENCES hive.ssb_1g_csv.supplier(s_suppkey);
hive.ssb_1g_csv.lineorder(lo_orderdate) REFERENCES hive.ssb_1g_csv.dates(d_datekey)",
-- 啟用查詢改寫。
"force_external_table_query_rewrite" = "TRUE"
)
AS SELECT
l.LO_ORDERDATE AS LO_ORDERDATE,
l.LO_ORDERKEY AS LO_ORDERKEY,
l.LO_PARTKEY AS LO_PARTKEY,
l.LO_SUPPKEY AS LO_SUPPKEY,
l.LO_QUANTITY AS LO_QUANTITY,
l.LO_EXTENDEDPRICE AS LO_EXTENDEDPRICE,
l.LO_DISCOUNT AS LO_DISCOUNT,
l.LO_REVENUE AS LO_REVENUE,
s.S_REGION AS S_REGION,
p.P_BRAND AS P_BRAND,
d.D_YEAR AS D_YEAR,
d.D_YEARMONTH AS D_YEARMONTH
FROM hive.ssb_1g_csv.lineorder AS l
INNER JOIN hive.ssb_1g_csv.supplier AS s ON s.S_SUPPKEY = l.LO_SUPPKEY
INNER JOIN hive.ssb_1g_csv.part AS p ON p.P_PARTKEY = l.LO_PARTKEY
INNER JOIN hive.ssb_1g_csv.dates AS d ON l.LO_ORDERDATE = d.D_DATEKEY;案例二:加速資料湖中的彙總和Join後彙總計算
物化視圖可用於加速彙總查詢,無論是在單個表上還是涉及多個表。
單表彙總查詢
對於典型的單表查詢,如果Query Profile顯示AGGREGATE節點消耗了大量時間,您可以使用常見的彙總運算元構建物化視圖。假設以下查詢速度較慢。
--Q4 SELECT lo_orderdate, count(distinct lo_orderkey) FROM hive.ssb_1g_csv.lineorder GROUP BY lo_orderdate ORDER BY lo_orderdate limit 100;Q4是一個計算每日去重訂單數量的查詢,因為count distinct的消耗較大,可以建立下列兩類物化視圖:
CREATE MATERIALIZED VIEW mv_2_1 DISTRIBUTED BY HASH(lo_orderdate) PARTITION BY LO_ORDERDATE REFRESH ASYNC EVERY(INTERVAL 1 DAY) AS SELECT lo_orderdate, count(distinct lo_orderkey) FROM hive.ssb_1g_csv.lineorder GROUP BY lo_orderdate; CREATE MATERIALIZED VIEW mv_2_2 DISTRIBUTED BY HASH(lo_orderdate) PARTITION BY LO_ORDERDATE REFRESH ASYNC EVERY(INTERVAL 1 DAY) AS SELECT -- lo_orderkey必須是BIGINT類型,以便可以用於查詢改寫。 lo_orderdate, bitmap_union(to_bitmap(lo_orderkey)) FROM hive.ssb_1g_csv.lineorder GROUP BY lo_orderdate;說明此處不要建立帶有LIMIT和ORDER BY子句的物化視圖,以避免改寫失敗。
多表彙總查詢
在涉及Join結果彙總的情境中,您可以在現有Join多表的物化視圖上建立嵌套物化視圖,進一步彙總串連結果。例如,根據案例一中的樣本,您可以建立以下物化視圖以加速Q1和Q2,因為它們的彙總模式相似。
CREATE MATERIALIZED VIEW mv_2_3 DISTRIBUTED BY HASH(lo_orderdate) PARTITION BY LO_ORDERDATE REFRESH ASYNC EVERY(INTERVAL 1 DAY) AS SELECT lo_orderdate, lo_discount, lo_quantity, d_year, d_yearmonth, SUM(lo_extendedprice * lo_discount) AS REVENUE FROM lineorder_flat_mv GROUP BY lo_orderdate, lo_discount, lo_quantity, d_year, d_yearmonth;當然,您也可以在單個物化視圖中同時執行Join和彙總計算。儘管這類的物化視圖改寫查詢的機會更少(因為涉及的計算更加具體),但在彙總後,其佔用儲存空間更少。您可以基於您的真實情境選擇。
CREATE MATERIALIZED VIEW mv_2_4 DISTRIBUTED BY HASH(lo_orderdate) PARTITION BY LO_ORDERDATE REFRESH ASYNC EVERY(INTERVAL 1 DAY) PROPERTIES ( "force_external_table_query_rewrite" = "TRUE" ) AS SELECT lo_orderdate, lo_discount, lo_quantity, d_year, d_yearmonth, SUM(lo_extendedprice * lo_discount) AS REVENUE FROM hive.ssb_1g_csv.lineorder, hive.ssb_1g_csv.dates WHERE lo_orderdate = d_datekey GROUP BY lo_orderdate, lo_discount, lo_quantity, d_year, d_yearmonth;
案例三:加速資料湖中的彙總後Join計算
在某些情況下,您可能需要首先對一個表執行彙總計算,然後再與其他表執行Join查詢。為了充分利用StarRocks的查詢改寫功能,我們建議您構建嵌套的物化視圖。樣本如下。
--Q5
SELECT * FROM (
SELECT
l.lo_orderkey, l.lo_orderdate, c.c_custkey, c_region, sum(l.lo_revenue)
FROM
hive.ssb_1g_csv.lineorder l
INNER JOIN (
SELECT distinct c_custkey, c_region
from
hive.ssb_1g_csv.customer
WHERE
c_region IN ('ASIA', 'AMERICA')
) c ON l.lo_custkey = c.c_custkey
GROUP BY l.lo_orderkey, l.lo_orderdate, c.c_custkey, c_region
) c1
WHERE
lo_orderdate = '19970503'Q5首先在customer表上執行彙總,然後在lineorder表上執行Join和彙總。類似的查詢可能涉及對c_region和lo_orderdate的不同過濾條件。為了利用查詢改寫功能,您可以建立兩個物化視圖,一個用於彙總,另一個用於串連。
--mv_3_1
CREATE MATERIALIZED VIEW mv_3_1
DISTRIBUTED BY HASH(c_custkey)
REFRESH ASYNC EVERY(INTERVAL 1 DAY)
PROPERTIES (
"force_external_table_query_rewrite" = "TRUE"
)
AS
SELECT distinct c_custkey, c_region from hive.ssb_1g_csv.customer;
--mv_3_2
CREATE MATERIALIZED VIEW mv_3_2
DISTRIBUTED BY HASH(lo_orderdate)
PARTITION BY LO_ORDERDATE
REFRESH ASYNC EVERY(INTERVAL 1 DAY)
PROPERTIES (
"force_external_table_query_rewrite" = "TRUE"
)
AS
SELECT l.lo_orderdate, l.lo_orderkey, mv.c_custkey, mv.c_region, sum(l.lo_revenue)
FROM hive.ssb_1g_csv.lineorder l
INNER JOIN mv_3_1 mv
ON l.lo_custkey = mv.c_custkey
GROUP BY l.lo_orderkey, l.lo_orderdate, mv.c_custkey, mv.c_region;案例四:對即時資料和資料湖中的歷史資料進行冷熱分離
例如以下情景:過去三天內的新資料直接寫入StarRocks,三天前的舊資料經過校對後批量寫入Hive。但是查詢仍然可能有涉及過去七天資料。在這種情況下,您可以使用物化視圖建立一個簡單的模型來自動到期資料。
CREATE MATERIALIZED VIEW mv_4_1
DISTRIBUTED BY HASH(lo_orderdate)
PARTITION BY LO_ORDERDATE
REFRESH ASYNC EVERY(INTERVAL 1 DAY)
AS
SELECT lo_orderkey, lo_orderdate, lo_revenue
FROM hive.ssb_1g_csv.lineorder
WHERE lo_orderdate<=current_date()
AND lo_orderdate>=date_add(current_date(), INTERVAL -4 DAY);您可以根據上層商務邏輯進一步構建視圖或物化視圖,以封裝計算。